home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / go32 / fs / fullscr.c < prev    next >
C/C++ Source or Header  |  1995-03-23  |  194KB  |  5,686 lines

  1. /* ---------------------------------------------------------------------- */
  2. /*                               LADYBUG                                  */
  3. /*                                                                        */
  4. /* Copyrighted 1994-1995 by Long Doan, ld@netrix.com                      */
  5. /* ---------------------------------------------------------------------- */
  6.  
  7. /* This debugger was derived from:
  8.  
  9.                        SALLY FULL SCREEN DEBUGGER
  10.                              version 0.91a
  11.                                    by
  12.                      Morten Welinder, terra@diku.dk
  13.  
  14. This debugger is free software; you can redistribute it and/or modify
  15. it under the terms of the GNU General Public License as published by
  16. the Free Software Foundation; either version 2, or (at your option)
  17. any later version.
  18.  
  19. This debugger is distributed in the hope that it will be useful,
  20. but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22. GNU General Public License for more details.
  23.  
  24. You should have received a copy of the GNU General Public License
  25. along with djgpp; see the file COPYING.  If not, write to
  26. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.     */
  27. /* ---------------------------------------------------------------------- */
  28. #define LADYBUG_VERSION 1.02
  29. #define MAJOR_VER 1
  30. #define MINOR_VER 02
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <ctype.h>
  35. #include <pc.h>
  36. #include <dos.h>
  37. #include <go32.h>
  38. #include <dpmi.h>
  39. #include <keys.h>
  40. #include <sys/stat.h>
  41. #include <fcntl.h>
  42. #include <setjmp.h>
  43. #define far
  44. #include "ed.h"
  45. #include "debug.h"
  46. #include "syms.h"
  47. #include "paging.h"
  48. #include "unassmbl.h"
  49. #include "npx.h"
  50. #include "serial.h"
  51. #include "fsfuncts.h"
  52. #include "xsupport.h"
  53. #include "perform.h"
  54. #include "io.h"
  55.  
  56. /* END_OF_INCLUDES */
  57. /* ---------------------------------------------------------------------- 
  58.    - Information about the initialization state of the debugger.  Actually
  59.    - I'm not sure that longjmp should ever be permitted.  
  60.    ---------------------------------------------------------------------- */
  61. int can_longjmp = 0;
  62. jmp_buf debugger_jmpbuf;
  63. /* ---------------------------------------------------------------------- 
  64.    - Information added to use com port - by Long Doan 
  65.    ---------------------------------------------------------------------- */
  66. static int using_com_port_num;
  67. int is_in_running_mode = 0;  
  68. /* ----------------------------------------------------------------------
  69.    - Display information.  
  70.    ---------------------------------------------------------------------- */
  71. int debug_screen_p;
  72. int toplines, bottomlines;
  73. int main_x1, main_x2, main_x3;
  74. /* ----------------------------------------------------------------------
  75.    - Information about panes.  
  76.    ---------------------------------------------------------------------- */
  77. #define PANECOUNT 11
  78. #define CODE_PANE_NUM       0
  79. #define REGISTER_PANE_NUM   1
  80. #define FLAG_PANE_NUM       2
  81. #define BREAKPOINT_PANE_NUM 3
  82. #define DATA_PANE_NUM       4
  83. #define NPX_PANE_NUM        5
  84. #define STACK_PANE_NUM      6
  85. #define INFO_PANE_NUM       7
  86. #define WHEREIS_PANE_NUM    8
  87. #define MODULE_PANE_NUM     9
  88. #define HELP_PANE_NUM      10
  89. static int pane, pane_positions[PANECOUNT], pane_pos;
  90. static int pane_offset[PANECOUNT];
  91. static word32 data_dump_origin, data_dump_last, data_dump_size;
  92. static word32 code_dump_origin, code_dump_last;
  93. static word32 *code_pane_pos, *stack_dump_pos;
  94. static int stack_dump_origin, stack_dump_last, stack_dump_more;
  95. static int breakpoint_origin;
  96. static word32 *whereis_pane_sym;
  97. static char **module_pane_text;
  98. static char **help_pane_text;
  99. static int whereis_sym_count, whereis_origin;
  100. static int module_text_count, module_origin;
  101. static int help_text_count, help_origin;
  102. static int reg_pane_origin, flag_pane_origin;
  103. static int code_pane_active;
  104. static int npx_pane_active;
  105. static int stack_pane_active;
  106. static int info_pane_active;
  107. static int whereis_pane_active;
  108. static int module_pane_active;
  109. static int help_pane_active;
  110. static int running_xsupport = 0;
  111. static char active_pane_name[20];
  112. /* ----------------------------------------------------------------------
  113.    - Menus 
  114.    ---------------------------------------------------------------------- */
  115. static MENU_ITEM File_Sub_Menu[] = { 
  116.        {"Current item              ", 1        , ""         , 0},
  117.        {"Read/write log      ~^X^F~", ITEM_TYPE, "\030\006" , 0},
  118.        {"View debug registers      ", ITEM_TYPE, ""         , 0},
  119.        {"Resize Screen             ", ITEM_TYPE, ""         , 0},
  120.        {"Monochrome Mode     ~^X m~", ITEM_TYPE, "\030m"    , 0},
  121.        {"Color Mode                ", ITEM_TYPE, ""         , 0},
  122.        {"Redirect IO               ", ITEM_TYPE, ""         , 0},
  123.        {"Save/load context   ~^X^V~", ITEM_TYPE, "\030\026" , 0},
  124.        {"Exit                ~^X^C~", ITEM_TYPE, "\030\003" , 0},
  125.        {0                           , 0        , ""         , 0}
  126. };
  127. static MENU_ITEM Pane_Sub_Menu[] = {
  128.        {"Current     ", 1        , "" , 0},
  129.        {"~P~revious  ", ITEM_TYPE, "p", 0},
  130.        {"~N~ext      ", ITEM_TYPE, "n", 0},
  131.        {"~B~reakpoint", ITEM_TYPE, "b", 0},
  132.        {"~C~ode      ", ITEM_TYPE, "c", 0},
  133.        {"~D~ata      ", ITEM_TYPE, "d", 0},
  134.        {"~F~lags     ", ITEM_TYPE, "f", 0},
  135.        {"~H~elp      ", ITEM_TYPE, "h", 0},
  136.        {"~I~nfo      ", ITEM_TYPE, "i", 0},
  137.        {"~M~odule    ", ITEM_TYPE, "m", 0},
  138.        {"Np~X~       ", ITEM_TYPE, "x", 0},
  139.        {"~R~egisters ", ITEM_TYPE, "r", 0},
  140.        {"~S~tack     ", ITEM_TYPE, "s", 0},
  141.        {"~W~here-is  ", ITEM_TYPE, "w", 0},
  142.        {"Resi~Z~e    ", ITEM_TYPE, "z", 0},
  143.        {0             , 0        , "" , 0}
  144. };
  145. static MENU_ITEM Help_Sub_Menu[] = {
  146.        {"Current     ", 1        , "" , 0},
  147.        {"~A~bout     ", ITEM_TYPE, "a", 0},
  148.        {"~H~elp      ", ITEM_TYPE, "h", 0},
  149.        {0             , 0        , "" , 0}
  150. };
  151. static MENU_ITEM Misc_Sub_Menu[] = {
  152.        {"Current      ", 1        , "" , 0},
  153.        {"~U~ser screen", ITEM_TYPE, "u", 0},
  154.        {"~E~valuate   ", ITEM_TYPE, "e", 0},
  155.        {"~R~efresh    ", ITEM_TYPE, "r", 0},
  156.        {0              , 0        , "" , 0}
  157. };
  158. static MENU_ITEM Main_Menu[] = {
  159.        {"Current "     , 1        , "" , 0            },
  160.        {"~F~ile  "     , MENU_TYPE, "f", File_Sub_Menu},
  161.        {"~P~ane  "     , MENU_TYPE, "p", Pane_Sub_Menu},
  162.        {"~L~ocal menu ", ITEM_TYPE, "l", 0            },
  163.        {"~M~isc  "     , MENU_TYPE, "m", Misc_Sub_Menu},
  164.        {"~H~elp  "     , MENU_TYPE, "h", Help_Sub_Menu},
  165.        {0           , 0        , "" , 0             }
  166. };
  167. /* ----------------------------------------------------------------------
  168.    - Odds and ends.
  169.    ---------------------------------------------------------------------- */
  170. #define MAXINSTLEN 16
  171. static int first_step;
  172. static int escaped, control_c, control_x;
  173. static word32 main_entry;
  174. static int has_npx = 1;
  175. NPX npx; /* non-static because declared so in "npx.h" */
  176. static char hexchars[] = "0123456789abcdef";
  177. #define MAX_REGISTERS 75
  178. #define SCROLL_COUNT 5
  179. #define ACTION_HIST_SIZE 40
  180. static word32 registers[MAX_REGISTERS];
  181. static char last_addr[4096];
  182. /* ---------------------------------------------------------------------- 
  183.    - The presentation order of registers in the register pane.  The three
  184.    - tables must of course match.  
  185.    ---------------------------------------------------------------------- */
  186. static char *regs_names[] = {
  187.   "eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp",
  188.   "cs",  "ds",  "es",  "fs",  "gs",  "ss",
  189.   "eip", "flg" };
  190. static word32 *regs_addr[] = {
  191.   &a_tss.tss_eax, &a_tss.tss_ebx, &a_tss.tss_ecx, &a_tss.tss_edx,
  192.   &a_tss.tss_esi, &a_tss.tss_edi, &a_tss.tss_ebp, &a_tss.tss_esp,
  193.   (word32 *)&a_tss.tss_cs, (word32 *)&a_tss.tss_ds,
  194.   (word32 *)&a_tss.tss_es, (word32 *)&a_tss.tss_fs,
  195.   (word32 *)&a_tss.tss_gs, (word32 *)&a_tss.tss_ss,
  196.   &a_tss.tss_eip, &a_tss.tss_eflags };
  197. /* ----------------------------------------------------------------------
  198.    - g: general, !: special, s: segment, f: flags, \0: end-of-table 
  199.    ---------------------------------------------------------------------- */
  200. static char regs_type[] = "ggggggg!ssssss!f";
  201. /* ---------------------------------------------------------------------- 
  202.    - Breakpoint data.  When breakpoints are actually put into the cpu debug
  203.    - registers, data breakpoints have first priority.  Any code breakpoints
  204.    - left over are set by patching the code to contain "Int 3".  
  205.    ---------------------------------------------------------------------- */
  206. typedef enum { BP_Code = 0, BP_Write = 1, BP_Read = 3 } BP_TYPE;
  207. typedef enum { BP_Normal = 0, BP_Count = 1, BP_Condition = 2 } BP_SUB_TYPE;
  208.  
  209. typedef struct
  210. {
  211.   word32 addr;
  212.   BP_TYPE type;
  213.   BP_SUB_TYPE sub_type;
  214.   int count;
  215.   char condition[200];
  216.   unsigned char length;       /* 1, 2, or 4 bytes */
  217.   unsigned char saved;
  218.   unsigned char savedbyte;    /* Patched-away byte. */
  219. } BP_ENTRY;
  220.  
  221. static int breakpoint_count;
  222. static BP_ENTRY *breakpoint_table;
  223. static unsigned char int03 = 0xcc;
  224.  
  225. #define MAX_UNDO 5           
  226. typedef struct undo_data {
  227.         word32 addr;
  228.         word32 value;
  229.         int size;
  230. } UNDO_DATA;
  231. typedef struct {
  232.         struct undo_data data[MAX_UNDO];
  233.         int count;                      
  234.         void (*free_entry)(word32);
  235. } UNDO_STRUCT;
  236. static UNDO_STRUCT data_undo;
  237. static UNDO_STRUCT register_undo;
  238. static UNDO_STRUCT breakpoint_undo;
  239. static UNDO_STRUCT npx_undo;
  240. /* ---------------------------------------------------------------------- */
  241. static void
  242. test_npx (void)
  243. { asm ("push    %eax            \n\
  244.     push    %ebx            \n\
  245.         movl    %cr0, %eax      \n\
  246.     andl    $0x04, %eax     \n\
  247.         jnz     Has_387         \n\
  248.         clts                    \n\
  249.         fninit                  \n\
  250.         movl    $_npx, %eax     \n\
  251.         movl    $0x5a5ah, (%eax)\n\
  252.         fnstsw  (%eax)          \n\
  253.         cmpb    $0, (%eax)      \n\
  254.         jne     No_387          \n\
  255.         fnstcw  (%eax)          \n\
  256.         movw    (%eax), %bx     \n\
  257.         and     $0x103f, %bx    \n\
  258.         cmpw    $0x3f, %bx      \n\
  259.         jne     No_387          \n\
  260.         fld1                    \n\
  261.         fldz                    \n\
  262.         fdiv                    \n\
  263.         fld     %st             \n\
  264.         fchs                    \n\
  265.         fcompp                  \n\
  266.         fstsw   (%eax)          \n\
  267.         movw    (%eax), %bx     \n\
  268.         sahf                    \n\
  269.         je      No_387          \n\
  270. Has_387:                        \n\
  271.         movl    $1, _has_npx    \n\
  272.         jmp     Test_done       \n\
  273. No_387:                         \n\
  274.         movl    $0, _has_npx    \n\
  275. Test_done:                      \n\
  276.         pop     %ebx            \n\
  277.         pop     %eax            "
  278.   );
  279. }
  280. /* ---------------------------------------------------------------------- */
  281. static void
  282. save_npx (void)
  283. {
  284. asm(                          "\n\
  285.     inb     $0xa0,%al      \n\
  286.         testb   $0x20,%al      \n\
  287.     jz      Lfclex_done    \n\
  288.     xorl    %eax,%eax      \n\
  289.     outb    %al,$0xf0      \n\
  290.     movb    $0x20,%al      \n\
  291.     outb    %al,$0xa0      \n\
  292.     outb    %al,$0x20      \n\
  293. Lfclex_done:                   \n\
  294.     movl    $_npx, %eax    \n\
  295.     fnsave  (%eax)         \n\
  296.     fwait                  "
  297.     );
  298. }
  299. /* ---------------------------------------------------------------------- */
  300. static void
  301. load_npx (void)
  302. {
  303. asm(                                                                   "\n\
  304.         movl    $_npx, %eax                                             \n\
  305.         frstor  (%eax)                                                  "
  306.     );
  307. /*  After line 1 */
  308. /*  movb    $0,4(%eax)  */
  309. /* clear pending exceptions */ 
  310. /* At least on my 486 there is no need to clear pending exceptions.  */
  311. }
  312. /* ---------------------------------------------------------------------- */
  313. /* Display the debugger screen (if not already displayed).  */
  314. static void
  315. debug_screen (void)
  316. { if (!debug_screen_p)
  317.     {
  318.       user_screen_save = get_screen ();
  319.       if (using_com_port_num)
  320.         screen_scroll (rows);
  321.       put_screen (debug_screen_save);
  322.       debug_screen_p = 1;
  323.     }
  324. }
  325. /* ---------------------------------------------------------------------- */
  326. /* Display the user screen (if not already displayed).  */
  327. static void
  328. user_screen (void)
  329. { if (debug_screen_p)
  330.     {
  331.       if (using_com_port_num)
  332.         screen_scroll (rows);
  333.       else
  334.         put_screen (user_screen_save);
  335.       free (user_screen_save);
  336.       debug_screen_p = 0;
  337.     }
  338. }
  339. /* ---------------------------------------------------------------------- */
  340. static void
  341. free_do_nothing (word32 addr)
  342. {
  343. }                                                    
  344. /* ---------------------------------------------------------------------- */
  345. static void
  346. free_breakpoint (word32 addr)
  347. { BP_ENTRY *bp_to_free = (BP_ENTRY *)addr;
  348.   free (bp_to_free);
  349. }                                                    
  350. /* ---------------------------------------------------------------------- */
  351. static void
  352. free_npx (word32 addr)
  353. { NPX *npx_to_free = (NPX *)addr;
  354.   free (npx_to_free);
  355. }                                                    
  356. /* ---------------------------------------------------------------------- */
  357. static void
  358. init_undo (UNDO_STRUCT *what_undo, void (*free_func)(word32))
  359. { what_undo->count = 0;                                     
  360.   what_undo->free_entry = free_func;
  361. }
  362. /* ---------------------------------------------------------------------- */
  363. static void
  364. reinit_undo (UNDO_STRUCT *what_undo)
  365. { while (what_undo->count)                 
  366.   { what_undo->count--;
  367.     what_undo->free_entry (what_undo->data[what_undo->count].value);
  368.   }
  369. }
  370. /* ---------------------------------------------------------------------- */
  371. static void
  372. put_undo (UNDO_STRUCT *what_undo, word32 addr, word32 val, int size)
  373. { if (what_undo->count == MAX_UNDO)
  374.   { int i;                          
  375.     what_undo->free_entry (what_undo->data[0].value);
  376.     for (i = 1; i < what_undo->count; i++)
  377.     { what_undo->data[i - 1].addr  = what_undo->data[i].addr;
  378.       what_undo->data[i - 1].value = what_undo->data[i].value;
  379.       what_undo->data[i - 1].size  = what_undo->data[i].size;
  380.     }
  381.     what_undo->count--;
  382.   }
  383.   what_undo->data[what_undo->count].addr  = addr;
  384.   what_undo->data[what_undo->count].value = val;
  385.   what_undo->data[what_undo->count].size  = size;
  386.   what_undo->count++;
  387. }
  388. /* ---------------------------------------------------------------------- */
  389. static int
  390. get_undo (UNDO_STRUCT *what_undo, word32 *addr, word32 *val, int *size)
  391. { if (what_undo->count <= 0)
  392.     return (0);      
  393.   what_undo->count--;                            
  394.   *addr = what_undo->data[what_undo->count].addr;
  395.   *val  = what_undo->data[what_undo->count].value;
  396.   *size = what_undo->data[what_undo->count].size;
  397.   return (1);
  398. }
  399. /* ---------------------------------------------------------------------- */
  400. typedef enum { not, com, mul, divi, add, sub, shl, shr,
  401.            and, xor, or, land, lor, less, greater, not_equal,
  402.                less_equal, great_equal, equal} OPR_Name;
  403. typedef struct {
  404.     char *str;
  405.     OPR_Name name;
  406. } OPR_TYPE;
  407. typedef struct {
  408.         OPR_TYPE *opers;
  409.         int opers_num;
  410. } OPR_CLASS;
  411.  
  412. static OPR_TYPE opers0[] = {     /* Lowest priority first */
  413.        {"||", lor        },
  414.        {"&&", land       },
  415.        {0   , 0          }
  416. };
  417. static OPR_TYPE opers1[] = {
  418.        {"==", equal      },
  419.        {">=", great_equal},
  420.        {"<=", less_equal },
  421.        {"!=", not_equal  },
  422.        {">" , greater    },
  423.        {"<" , less       },
  424.        {0   , 0          }
  425. };
  426. static OPR_TYPE opers2[] = {
  427.        {"|" , or         },
  428.        {"^" , xor        },
  429.        {"&" , and        },
  430.        {0   , 0          }
  431. };
  432. static OPR_TYPE opers3[] = {
  433.        {">>", shr        },
  434.        {"<<", shl        },
  435.        {0   , 0          }
  436. };
  437. static OPR_TYPE opers4[] = {
  438.        {"-" , sub        },
  439.        {"+" , add        },
  440.        {0   , 0          }
  441. };
  442. static OPR_TYPE opers5[] = {
  443.        {"/" , divi       },
  444.        {"*" , mul        },
  445.        {0   , 0          }
  446. };
  447. static OPR_TYPE opers6[] = {     /* Unary, left until the end. */
  448.        {"~" , com        },
  449.        {"!" , not        },
  450.        {0   ,0           }
  451. };
  452. static OPR_CLASS operators[] = {
  453.        {opers0, 2        },
  454.        {opers1, 6        },
  455.        {opers2, 3        },
  456.        {opers3, 2        },
  457.        {opers4, 2        },
  458.        {opers5, 2        },
  459.        {opers6, 2        },
  460.        {0     , 0        }
  461. };
  462. static char l_str[200], r_str[200];
  463. /* ---------------------------------------------------------------------- */
  464. static char *
  465. i_strstr (char *s1, char *s2)
  466. { int i, len1, len2;
  467.   if (!s1 || !s2)
  468.     return (0);
  469.   len1 = strlen (s1);
  470.   len2 = strlen (s2);
  471.   if (!len2)
  472.     return (s1);
  473.   if (!len1 || len1 < len2)
  474.     return (0);
  475.   for (i = len1 - len2; i >= 0; i--)
  476.     if (strncmp (s1 + i, s2, len2) == 0)
  477.       return (s1 + i);
  478.   return (0);
  479. }
  480. /* ---------------------------------------------------------------------- */
  481. static void
  482. break_up (char *expr, OPR_Name *opr_num, int *found)
  483. { word32 pos, maxpos;
  484.   int i, j, k = 1, len = strlen(expr);
  485.   char *ptr = 0, *testptr = 0;
  486.  
  487.   l_str[0] = '\0';
  488.   r_str[0] = '\0';
  489.   *found = 0;
  490.   for (i = 0; !(*found) && operators[i].opers; i++)
  491.   { maxpos = 0;
  492.     k = 0;
  493.     for (j = 0; j < operators[i].opers_num; j++)
  494.     { testptr = i_strstr(expr, operators[i].opers[j].str);
  495.       pos = (word32)testptr;
  496.       if (pos)
  497.       { pos -= (word32)expr;
  498.         if (pos > maxpos)
  499.         { maxpos = pos;
  500.           ptr = testptr;
  501.           k = j;
  502.         }
  503.         *found = 1;
  504.       }
  505.     }
  506.   }
  507.   if (*found)
  508.   { i--;
  509.     len -= strlen (ptr);
  510.     if (len > 0)
  511.       strncpy(l_str, expr, len);
  512.     l_str[len] = 0;
  513.     len = strlen (l_str) - 1;
  514.     while (len >= 0 && l_str[len] == ' ')
  515.       l_str[len--] = 0;
  516.     ptr++;
  517.     *opr_num = operators[i].opers[k].name;
  518.     switch (*opr_num)
  519.     {
  520.       case shl:
  521.       case shr:
  522.       case land:
  523.       case lor:
  524.       case not_equal:
  525.       case less_equal:
  526.       case great_equal:
  527.       case equal:
  528.     ptr++;
  529.         break;
  530.       default:
  531.         break;
  532.     }
  533.     while (*ptr && *ptr == ' ')
  534.       ptr++;
  535.     strcpy(r_str, ptr);
  536.   }
  537. }
  538. /* ---------------------------------------------------------------------- */
  539. static long
  540. parse_expression_without_paren (int size, char *expr, int *okp)
  541. {
  542.   long l_val, r_val, result = 0;
  543.   char *l_expr, *r_expr;
  544.   OPR_Name opr_num;
  545.   int found;
  546.  
  547.   break_up(expr, &opr_num, &found);
  548.   if (found)
  549.   { if (opr_num == divi && expr[0] == '/')
  550.     { result = syms_name2val(expr);
  551.       if (undefined_symbol)
  552.       { *okp = ParseError_undef;
  553.         return 0;
  554.       }
  555.       *okp = ParseError_ok;
  556.     } else
  557.     { l_expr = strdup(l_str);
  558.       r_expr = strdup(r_str);
  559.       r_val = parse_expression_without_paren (size, r_expr, okp);
  560.       free (r_expr);
  561.       if (*okp != ParseError_ok)
  562.       { free (l_expr);
  563.         return 0;
  564.       }
  565.       l_val = parse_expression_without_paren (size, l_expr, okp);
  566.       free (l_expr);
  567.       if (*okp != ParseError_ok)
  568.         return 0;
  569.       *okp = ParseError_ok;
  570.       switch (opr_num)
  571.       { case not:
  572.           result = !r_val;
  573.           break;
  574.         case com:
  575.           result = ~r_val;
  576.           break;
  577.         case mul:
  578.       result = l_val * r_val;
  579.           break;
  580.         case divi:
  581.           if (r_val == 0)
  582.           { *okp = ParseError_divzero;
  583.         return 0;
  584.           } else
  585.             result = l_val / r_val;
  586.           break;
  587.         case add:
  588.           result = l_val + r_val;
  589.           break;
  590.         case sub:
  591.           result = l_val - r_val;
  592.           break;
  593.         case shl:
  594.           result = l_val << r_val;
  595.           break;
  596.         case shr:
  597.           result = l_val >> r_val;
  598.           break;
  599.         case and:
  600.           result = l_val & r_val;
  601.           break;
  602.         case xor:
  603.           result = l_val ^ r_val;
  604.           break;
  605.         case or :
  606.           result = l_val | r_val;
  607.           break;
  608.         case land:
  609.           result = l_val && r_val;
  610.           break;
  611.         case lor:
  612.           result = l_val || r_val;
  613.           break;
  614.         case equal:
  615.           result = (l_val == r_val);
  616.           break;
  617.         case great_equal:
  618.           result = (l_val >= r_val);
  619.           break;
  620.         case less_equal:
  621.           result = (l_val <= r_val);
  622.           break;
  623.         case not_equal:
  624.           result = (l_val != r_val);
  625.           break;
  626.         case greater:
  627.           result = (l_val > r_val);
  628.           break;
  629.         case less:
  630.           result = (l_val < r_val);
  631.           break;
  632.       }
  633.     }
  634.   } else
  635.   { result = syms_name2val(expr);
  636.     if (undefined_symbol)
  637.     {
  638.       *okp = ParseError_undef;
  639.       return 0;
  640.     }
  641.     *okp = ParseError_ok;
  642.   }
  643.   switch (size)
  644.   { case 1:
  645.       return (short)(result & 0xff);
  646.     case 2:
  647.       return (int)(result & 0xffff);
  648.     case 4:          /* Fall through */
  649.     default:
  650.       return result;
  651.   }
  652. }
  653. /* ---------------------------------------------------------------------- */
  654. long
  655. parse_expression (int size, char *expr, int *okp)
  656. { int len = strlen (expr);
  657.   char *new_exp1 = alloca (len * 2 + 10), *new_exp2 = alloca (len * 2 + 10);
  658.   int left_paren = 0, right_paren = 0, i, found = 1;
  659.   char lookfor = ']';
  660.   long temp_value;
  661.              
  662.   *okp = ParseError_ok;
  663.   strcpy (new_exp1, expr);
  664.   while (found)
  665.   { for (i = 0; (i < len) && (new_exp1[i] != lookfor); i++)
  666.       ;            
  667.     if (i == len)
  668.       i = len - 1;
  669.     if (new_exp1[i] != lookfor)
  670.     { if (lookfor == ']')
  671.         lookfor = ')';
  672.       else
  673.         found = 0;
  674.     } else
  675.     { right_paren = i;        
  676.       if (lookfor == ']')
  677.         lookfor = '[';
  678.       else
  679.         lookfor = '(';
  680.       for (i = right_paren - 1; (i >= 0) && (new_exp1[i] != lookfor); i--)
  681.         ;         
  682.       if (i < 0)
  683.         i = 0;
  684.       if (new_exp1[i] != lookfor)
  685.       { *okp = ParseError_paren;
  686.         return (0);
  687.       }
  688.       left_paren = i;
  689.       temp_value = 0;
  690.       for (i = left_paren + 1; (i < right_paren); i++, temp_value++)
  691.         new_exp2[temp_value] = new_exp1[i];
  692.       new_exp2[temp_value] = 0;                                    
  693.       temp_value = parse_expression (size, new_exp2, okp);
  694.       if (*okp != ParseError_ok)
  695.         return (0);            
  696.       if (lookfor == '[')
  697.       { switch (new_exp1[++right_paren])
  698.         { case 'b':
  699.             i = 1;
  700.             break;
  701.           case 'h':
  702.             i = 2;
  703.             break;
  704.           case 'f':
  705.             i = 4;
  706.             break;
  707.           default:
  708.             i = 4;
  709.             right_paren--;
  710.             break;
  711.         }
  712.         if (valid_addr (temp_value, i))
  713.           read_child (temp_value, &temp_value, i);
  714.         else
  715.         { *okp = ParseError_addr;
  716.           return (0);
  717.         }      
  718.         switch (i)
  719.         { case 1:
  720.             temp_value &= 0x000000ff;
  721.             break;
  722.           case 2:
  723.             temp_value &= 0x0000ffff;
  724.             break;  
  725.         }
  726.       }
  727.       
  728.       strncpy(l_str, new_exp1, left_paren);
  729.       strcpy(r_str, new_exp1 + right_paren + 1);
  730.       l_str[left_paren] = 0;
  731.       r_str[len - right_paren + 1] = 0;
  732.       sprintf (new_exp2, "%s0x%08lx%s", l_str, temp_value, r_str);
  733.       strcpy (new_exp1, new_exp2);
  734.       len = strlen (new_exp1); 
  735.  
  736.       if (lookfor == '[')
  737.         lookfor = ']';
  738.       else
  739.         lookfor = ')';
  740.     }
  741.   }                                          
  742.   return (parse_expression_without_paren (size, new_exp1, okp));
  743. }
  744. /* ---------------------------------------------------------------------- */
  745. static long
  746. read_eval (int *okp, char *starttext)
  747. {
  748.   long result;
  749.  
  750.   *okp = !read_string (starttext);
  751.   if (*okp && read_buffer[0] != '\0')
  752.   {
  753.     result = parse_expression (4, read_buffer, okp);
  754.     if (*okp == ParseError_ok)
  755.     { *okp = 1;
  756.       return (result);
  757.     }
  758.     switch (*okp)
  759.     { case ParseError_addr:
  760.         message (CL_Error, "Reference to an invalid address.");
  761.         break;  
  762.       case ParseError_divzero:
  763.         message (CL_Error, "Divide by zero.");
  764.         break;
  765.       case ParseError_paren:
  766.         message (CL_Error, "Unbalanced [] or ().");
  767.         break;
  768.       case ParseError_syntax:
  769.         message (CL_Error, "Syntax error.");
  770.         break;                          
  771.       case ParseError_undef:
  772.         message (CL_Error, "Undefined symbol.");
  773.         break;
  774.     }     
  775.     *okp = 0;
  776.     return (0);
  777.   }
  778.   else
  779.     return *okp = 0;
  780. }
  781. /* ---------------------------------------------------------------------- */
  782. inline static int
  783. valid_instaddr (word32 vaddr)
  784. {
  785.   return valid_addr (vaddr, MAXINSTLEN);
  786. }
  787. /* ---------------------------------------------------------------------- */
  788. /* Set physical breakpoint registers from virtual ones.  */
  789. static void
  790. activate_breakpoints (void)
  791. {
  792.   int b, no;
  793.   BP_ENTRY *bep;
  794.  
  795.   no = 0;
  796.   edi.dr[7] = 0;
  797.   /* First handle data breakpoints.  */
  798.   for (b = 0, bep = breakpoint_table; b < breakpoint_count; b++, bep++)
  799.     if (no <= 3 && bep->type != BP_Code)
  800.       {
  801.     bep->saved = 0;
  802.     edi.dr[7] |= ((bep->type + ((bep->length - 1) << 2)) << (16 + 4 * no)
  803.               | (2 << (2 * no)));
  804.     edi.dr[no] = bep->addr + edi.app_base;
  805.     no++;
  806.       }
  807.  
  808.   /* Now handle code breakpoint.  */
  809.   for (b = 0, bep = breakpoint_table; b < breakpoint_count; b++, bep++)
  810.     if (bep->type == BP_Code)
  811.       if (no <= 3)
  812.     {
  813.       bep->saved = 0;
  814.       edi.dr[7] |= ((BP_Code << (16 + 4 * no)) | (2 << (2 * no)));
  815.       edi.dr[no] = bep->addr + edi.app_base;
  816.       no++;
  817.       edi.dr[7] |= 0x00000300L;  /* For 386s we set GE & LE bits.  */
  818.     }
  819.       else
  820.     {
  821.       bep->saved = valid_addr (bep->addr, 1);
  822.       if (bep->saved)
  823.         {
  824.           read_child (bep->addr, &bep->savedbyte, 1);
  825.           write_child (bep->addr, &int03, 1);
  826.         }
  827.     }
  828. }
  829. /* ---------------------------------------------------------------------- */
  830. /* Un-patch code.  */
  831. static void
  832. deactivate_breakpoints (void)
  833. { int b;
  834.   BP_ENTRY *bep;
  835.  
  836.   for (b = 0, bep = breakpoint_table; b < breakpoint_count; b++, bep++)
  837.     if (bep->saved)
  838.       write_child (bep->addr, &bep->savedbyte, 1);
  839. }
  840. /* ---------------------------------------------------------------------- */
  841. static int
  842. get_breakpoint (BP_TYPE type, int length, word32 addr)
  843. { int b;
  844.  
  845.   for (b = 0; b < breakpoint_count; b++)
  846.     if ((breakpoint_table[b].type == type) &&
  847.         ((breakpoint_table[b].length == length) || (length == -1)) &&
  848.         (breakpoint_table[b].addr == addr))
  849.       return b;
  850.   return -1;
  851. }
  852. /* ---------------------------------------------------------------------- */
  853. static void
  854. reset_breakpoint (int b)
  855. { BP_ENTRY *del_bp = malloc (sizeof (BP_ENTRY));
  856.   
  857.   del_bp->addr     = breakpoint_table[b].addr;
  858.   del_bp->type     = breakpoint_table[b].type;
  859.   del_bp->length   = breakpoint_table[b].length;
  860.   del_bp->sub_type = breakpoint_table[b].sub_type;
  861.   del_bp->count    = breakpoint_table[b].count;
  862.   strcpy (del_bp->condition, breakpoint_table[b].condition);
  863.   put_undo (&breakpoint_undo, 1, (word32)del_bp, 1);
  864.   breakpoint_table[b] = breakpoint_table[--breakpoint_count];
  865.   breakpoint_table
  866.     = realloc (breakpoint_table, breakpoint_count * sizeof (BP_ENTRY));
  867. }
  868. /* ---------------------------------------------------------------------- */
  869. static int
  870. set_breakpoint (BP_TYPE type, int length, word32 addr)
  871. { int b;
  872.  
  873.   b = breakpoint_count;
  874.   breakpoint_table
  875.     = realloc (breakpoint_table, ++breakpoint_count * sizeof (BP_ENTRY));
  876.   breakpoint_table[b].addr = addr;
  877.   breakpoint_table[b].type = type;
  878.   breakpoint_table[b].length = length;
  879.   breakpoint_table[b].sub_type = 0;
  880.   breakpoint_table[b].count = 0;
  881.   breakpoint_table[b].condition[0] = '\0';
  882.   return b;
  883. }
  884. /* ---------------------------------------------------------------------- */
  885. static void
  886. format_type (char *output, char *input)
  887. { int ok;
  888.   long temp = parse_expression (4, input, &ok);
  889.   
  890.   if (ok != ParseError_ok)
  891.     temp = 4;
  892.   switch (temp)
  893.   { case 0:
  894.       sprintf (output, "%ld (%s)", temp, "Code breakpoint");
  895.       break;
  896.     case 1:
  897.       sprintf (output, "%ld (%s)", temp, "Data-write breakpoint");
  898.       break;
  899.     case 3:
  900.       sprintf (output, "%ld (%s)", temp, "Data-read/write breakpoint");
  901.       break;                                            
  902.     default:
  903.       sprintf (output, "%ld (%s)", temp, "Invalid breakpoint type");
  904.       break;
  905.   }
  906. }
  907. /* ---------------------------------------------------------------------- */
  908. static void
  909. format_subt (char *output, char *input)
  910. { int ok;
  911.   long temp = parse_expression (4, input, &ok);
  912.   
  913.   if (ok != ParseError_ok)
  914.     temp = 3;
  915.   switch (temp)
  916.   { case 0:
  917.       sprintf (output, "%ld (%s)", temp, "Normal breakpoint");
  918.       break;
  919.     case 1:
  920.       sprintf (output, "%ld (%s)", temp, "Countdown breakpoint");
  921.       break;
  922.     case 2:
  923.       sprintf (output, "%ld (%s)", temp, "Conditional breakpoint");
  924.       break;                                            
  925.     default:
  926.       sprintf (output, "%ld (%s)", temp, "Invalid breakpoint type");
  927.       break;
  928.   }
  929. }
  930. /* ---------------------------------------------------------------------- */
  931. static void
  932. init_type (char *output, char *input, word32 addr)
  933. { char *temp = alloca (16);
  934.  
  935.   sprintf (input, "%d", *(int *)addr);
  936.   sprintf (temp, "%08lx", *(word32 *)addr);
  937.   format_type (output, temp);
  938. }
  939. /* ---------------------------------------------------------------------- */
  940. static void
  941. init_subt (char *output, char *input, word32 addr)
  942. { char *temp = alloca (16);
  943.  
  944.   sprintf (input, "%d", *(int *)addr);
  945.   sprintf (temp, "%08lx", *(word32 *)addr);
  946.   format_subt (output, temp);
  947. }
  948. /* ---------------------------------------------------------------------- */
  949. static int
  950. edit_breakpoint (int bp_num)
  951. { word32 addr;
  952.   int    type = 0, sub_type = 0, count = 0, size = 4, ret = 5;
  953.   char   *condition = alloca (max_cols);
  954.   static DIALOG_ITEM dialog_data[] = {
  955.     {"Address  :", 0 , 50, 1, format_addr, eval_word, init_addr, editor},
  956.     {"Type     :", 0 , 30, 1, format_type, eval_word, init_type, editor},
  957.     {"Class    :", 0 , 30, 1, format_subt, eval_word, init_subt, editor},
  958.     {"Count    :", 0 , 10, 1, format_deci, eval_word, init_deci, editor},
  959.     {"Size     :", 0 , 02, 1, format_deci, eval_word, init_deci, editor},
  960.     {"Condition:", 0 , 70, 1, format_asis, eval_asis, init_asis, editor},
  961.     {0           , 0 , 0 , 0, 0          , 0        , 0        , 0     }
  962.   };
  963.   static BUTTON_ITEM button_data[] = {
  964.     {"   OK   ", 0, action_done},
  965.     {" Cancel ", 0, action_done},
  966.     {0         , 0, 0          }
  967.   };
  968.  
  969.   addr      = breakpoint_table[bp_num].addr;
  970.   type      = breakpoint_table[bp_num].type;
  971.   sub_type  = breakpoint_table[bp_num].sub_type;
  972.   count     = breakpoint_table[bp_num].count;
  973.   size      = breakpoint_table[bp_num].length;
  974.   strcpy(condition,breakpoint_table[bp_num].condition);
  975.   if (size != 1 && size != 2)
  976.     size = 4;
  977.  
  978.   dialog_data[0].return_addr = (word32)&addr;
  979.   dialog_data[1].return_addr = (word32)&type;
  980.   dialog_data[2].return_addr = (word32)&sub_type;
  981.   dialog_data[3].return_addr = (word32)&count;
  982.   dialog_data[4].return_addr = (word32)&size;
  983.   dialog_data[5].return_addr = (word32)condition;
  984.   dialog ("Edit Breakpoint", dialog_data, button_data, &ret);
  985.   if (ret == 1)
  986.   { if (size != 1 && size != 2)
  987.       size = 4;
  988.     breakpoint_table[bp_num].addr     = addr;
  989.     breakpoint_table[bp_num].type     = type;
  990.     breakpoint_table[bp_num].sub_type = sub_type;
  991.     breakpoint_table[bp_num].count    = count;
  992.     breakpoint_table[bp_num].length   = size;
  993.     strcpy(breakpoint_table[bp_num].condition,condition);
  994.     return (0);
  995.   } else
  996.     return (1);
  997. }
  998. /* ---------------------------------------------------------------------- */
  999. /* From ORIGIN skip COUNT instructions forward (positive count) or
  1000.    backwards (negative count).  Backwards skipping cannot be assumed to
  1001.    be working 100% perfectly, but in the presense of debug information
  1002.    it is probably very, very close.
  1003.  
  1004.    This function works poorly close to the extremes of segments.  */
  1005.  
  1006. static int
  1007. code_skip (int origin, int count)
  1008. {
  1009.   int len, *next, i, j, k, instcount, done, leave;
  1010.   char *state, *inst, *source;
  1011.  
  1012.   if (count >= 0)
  1013.   { while (count-- > 0)
  1014.       if (valid_instaddr (origin))
  1015.       { unassemble_proper (origin, &len);
  1016.         origin += len;
  1017.       }    else
  1018.         origin ++;
  1019.     return origin;
  1020.   } else
  1021.   { count = -count;
  1022.     instcount = MAXINSTLEN * (count + 16) + 1;
  1023.     next = alloca (instcount * sizeof (int));
  1024.     memset (next, 0, instcount * sizeof (int));
  1025.     state = alloca (instcount * sizeof (char));
  1026.     memset (state, 0, instcount * sizeof (char));
  1027.  
  1028.     done = 0;
  1029.     do
  1030.     { for (i = 0; i < 2 * count; i++)
  1031.       { done++;
  1032.         j = origin - done;
  1033.         if (valid_instaddr (j))
  1034.         { inst = unassemble_proper (j, &len);
  1035.           source = unassemble_source (j);
  1036.           next[done] = j + len;
  1037.           if (source)
  1038.           { leave = 0;
  1039.             k = done;
  1040.             while (j < origin && state[k] == 0 && !leave)
  1041.             { j++;
  1042.               state[k--] = 2;
  1043.               while (len-- > 1)
  1044.               { j++;
  1045.                 state[k--] = 3;
  1046.               }
  1047. /* -------------------------------------------------------------------
  1048.    - Since code and data is "never" mixed in 32 bit code we don't need this.  
  1049.    -------------------------------------------------------------------*/
  1050. #if 0
  1051.               leave = (strncmp (inst, "jmp", 3) == 0
  1052.                        || strncmp (inst, "ret", 3) == 0
  1053.                        || strncmp (inst, "iret", 4) == 0);
  1054. #endif
  1055.               if (!leave)
  1056.                 inst = unassemble_proper (j, &len);
  1057.             }
  1058.           }
  1059.         } else
  1060.         { state[done] = 2;
  1061.           next[done] = j + 1;
  1062.         }
  1063.       }
  1064.       j = 1;
  1065.       k = count;
  1066.       while (k > 0 && j <= done && state[j] >= 2)
  1067.         if (state[j++] == 2)
  1068.           k--;
  1069.     } while (k > 0 && done + 2 * count <= instcount);
  1070.     if (k == 0)
  1071.       return origin - j + 1;
  1072.     else
  1073.     { i = origin;
  1074.       k = 0;
  1075.       while (count > 0 && k <= done)
  1076.       { leave = 0;
  1077.         j = MAXINSTLEN;
  1078.         while (!leave && j > 1)
  1079.           if (j + k <= done && next[j + k] == i)
  1080.             leave = 1;
  1081.           else
  1082.             j--;
  1083.         if (!leave)
  1084.           i--, k++;
  1085.         else
  1086.           i -= j, k += j;
  1087.         count--;
  1088. /* -------------------------------------------------------------------
  1089.    - If there is a source line, that also counts toward the number of lines
  1090.    ------------------------------------------------------------------- */
  1091.         source = unassemble_source (i);
  1092.         if (source)
  1093.           count--;
  1094.       }      
  1095.       return i;
  1096.     }
  1097.   }
  1098. }
  1099. /* ---------------------------------------------------------------------- */
  1100. static void
  1101. code_pane_goto (word32 v)
  1102. { int i = 0;
  1103.  
  1104.   if (v >= code_dump_origin && v <= code_dump_last)
  1105.   { while (code_pane_pos[i] < v)
  1106.       i++;
  1107.     if (code_pane_pos [i] == code_pane_pos[i+1])
  1108.       i++;
  1109.   } else
  1110.   { code_dump_origin = v;
  1111.     if (valid_instaddr (v) && unassemble_source (v))
  1112.       i++;
  1113.   }
  1114.   if (pane == 0)
  1115.     pane_pos = i;
  1116.   else
  1117.     pane_positions[0] = i;
  1118. }
  1119. /* ---------------------------------------------------------------------- */
  1120. inline static void
  1121. go (int bp)
  1122. /* ------------------------------------------------------------
  1123.    - These modifications cannot be undone after run/trace/step 
  1124.    ------------------------------------------------------------ */
  1125.   reinit_undo (&data_undo);
  1126.   reinit_undo (®ister_undo);
  1127.   reinit_undo (&npx_undo);
  1128.   if (bp) 
  1129.     activate_breakpoints ();
  1130.   is_in_running_mode = 1;
  1131.   run_child ();
  1132.   is_in_running_mode = 0;
  1133.   if (bp)
  1134.     deactivate_breakpoints ();
  1135. }
  1136. /* ---------------------------------------------------------------------- */
  1137. static void
  1138. trace_over_bp (void)
  1139. { int len;
  1140.   char *inst;
  1141.   word32 old_addr = a_tss.tss_eip;
  1142.  
  1143.   inst = unassemble_proper (old_addr, &len);
  1144.   if (strcmp (inst, "popf") == 0 || strcmp (inst, "pushf") == 0)
  1145.   { edi.dr[7] = 0;
  1146.     edi.dr[7] |= ((BP_Code << 16) | 2);
  1147.     edi.dr[0] = old_addr + len + edi.app_base;
  1148.     edi.dr[7] |= 0x00000300L;
  1149.  
  1150.     is_in_running_mode = 1;
  1151.     run_child ();
  1152.     is_in_running_mode = 0;
  1153.   } else
  1154.   { a_tss.tss_eflags |= 0x0100;
  1155.     edi.dr[7] = 0;
  1156.     is_in_running_mode = 1;
  1157.     run_child ();
  1158.     is_in_running_mode = 0;
  1159.     a_tss.tss_eflags &= ~0x0100;
  1160.   }
  1161. }
  1162. /* ---------------------------------------------------------------------- */
  1163. static char condition[200];
  1164. /* ---------------------------------------------------------------------- */
  1165. static void
  1166. go_til_true_stop (int *terminated, int *int03hit)
  1167. { int b, i, keep_going = 1;
  1168.  
  1169.   while (keep_going)
  1170.   { go (1);
  1171.     i = a_tss.tss_irqn;
  1172.     *terminated = (i == 0x21) && (a_tss.tss_eax & 0xff00) == 0x4c00;
  1173.     *int03hit = (i == 0x03) &&
  1174.                 (get_breakpoint (BP_Code, -1, a_tss.tss_eip - 1) != -1);
  1175.     if (*terminated)
  1176.       a_tss.tss_eip -= 2;  /* point back to Int 21h */
  1177.     else if (*int03hit)
  1178.       a_tss.tss_eip--;     /* point back to Int 3 */
  1179.     if (*terminated)
  1180.       return;                           
  1181.  
  1182.     if (i == 1 || *int03hit)
  1183.     { int no;
  1184.   
  1185.       no = -1;
  1186.       for (b = 0; no == -1 && b <= 3; b++)
  1187.         if ((edi.dr[6] & (1 << b)) && (edi.dr[7] & (3 << (b * 2))))
  1188.           no = b;
  1189.       if (no != -1)
  1190.       { b = no;
  1191.         no = get_breakpoint ((edi.dr[7] >> (16 + 4 * no)) & 3,
  1192.                              ((edi.dr[7] >> (18 + 4 * no)) & 3) + 1,
  1193.                              edi.dr[no] - edi.app_base);
  1194.         if (no == -1)
  1195.         { no = b;
  1196.           no = get_breakpoint ((edi.dr[7] >> (16 + 4 * no)) & 3,
  1197.                                -1, edi.dr[no] - edi.app_base);
  1198.         }
  1199.       }
  1200.       else if (*int03hit)
  1201.         no = get_breakpoint (BP_Code, -1, a_tss.tss_eip);
  1202.       if (no != -1)
  1203.       { switch (breakpoint_table[no].sub_type)
  1204.         { case 1:                      /* Count down */
  1205.             if (breakpoint_table[no].count)
  1206.               breakpoint_table[no].count--;
  1207.             else
  1208.               keep_going = 0;
  1209.             break;
  1210.           case 2:                      /* Conditional */
  1211.           { int ofs, satisfy;
  1212.  
  1213.             strcpy (condition, breakpoint_table[no].condition);
  1214.             satisfy = parse_expression(breakpoint_table[no].length, 
  1215.                                        condition, &ofs);
  1216.             if (ofs != ParseError_ok)
  1217.               break;
  1218.             if (satisfy != 0)
  1219.               keep_going = 0;
  1220.             break;
  1221.           }
  1222.           default:
  1223.             keep_going = 0;
  1224.         }
  1225.         if (keep_going)
  1226.           trace_over_bp ();
  1227.       } else
  1228.         keep_going = 0;
  1229.     } else
  1230.       keep_going = 0;
  1231.   }
  1232. }
  1233. /* ---------------------------------------------------------------------- */
  1234. static void
  1235. step_over (int *terminated, int *int03hit, int len)
  1236. { int b, has_break_point = 0;
  1237.   word32 old_addr = 0;
  1238.   int sub_type = 0, count = 0;
  1239.   char *cond = 0;
  1240.  
  1241.   b = get_breakpoint (BP_Code, -1, a_tss.tss_eip);
  1242.   if (b != -1)
  1243.   { old_addr  = breakpoint_table[b].addr;
  1244.     sub_type  = breakpoint_table[b].sub_type;
  1245.     count     = breakpoint_table[b].count;
  1246.     cond      = strdup (breakpoint_table[b].condition);
  1247.     reset_breakpoint (b);
  1248.     has_break_point = 1;
  1249.   }
  1250.   b = set_breakpoint (BP_Code, 0, a_tss.tss_eip + len);
  1251.   go_til_true_stop (terminated, int03hit);
  1252.   reset_breakpoint (b);
  1253.   if (has_break_point)
  1254.   { b = set_breakpoint (BP_Code, 0, old_addr);
  1255.     breakpoint_table[b].sub_type = sub_type;
  1256.     breakpoint_table[b].count    = count;
  1257.     strcpy(breakpoint_table[b].condition, cond);
  1258.     free (cond);
  1259.   }
  1260. }
  1261. /* ---------------------------------------------------------------------- */
  1262. static void
  1263. step (int kind)
  1264. { int i, b, len, terminated = 0, int03hit = 0, refmem;
  1265.   char *inst = 0;
  1266.  
  1267.   switch (kind)
  1268.   { case 0:
  1269.       inst = unassemble_proper (a_tss.tss_eip, &len);
  1270.       if (strcmp (inst, "popf") == 0 || strcmp (inst, "pushf") == 0)
  1271.     kind = 1;  /* Push the right value of eflags (no trace flag).  */
  1272.       break;
  1273.     case 1:
  1274.       if (first_step)
  1275.     kind = 3;
  1276.       else
  1277.       { inst = unassemble_proper (a_tss.tss_eip, &len);
  1278.         if (strncmp (inst, "loop", 4)
  1279.             && strncmp (inst, "call", 4)
  1280.             && strncmp (inst, "int", 3) )
  1281.           kind = 0;
  1282.         break;
  1283.       }
  1284.   }
  1285.   switch (kind)
  1286.   { case 0: /* "Trace" */
  1287.       a_tss.tss_eflags |= 0x0100;
  1288.       edi.dr[7] = 0;
  1289.       refmem = strchr (inst, '[') != 0;
  1290.       if (refmem)
  1291.     /* Assume that all access to code and stack segments are safe.
  1292.        This should hold unless you do something extra-ordinary dirty.  */
  1293.     if (((a_tss.tss_ds == a_tss.tss_cs) || (a_tss.tss_ds == a_tss.tss_ss))
  1294.          && ((a_tss.tss_es == a_tss.tss_cs) || (a_tss.tss_es == a_tss.tss_ss))
  1295.          && ((a_tss.tss_fs == a_tss.tss_cs) || (a_tss.tss_fs == a_tss.tss_ss)
  1296.             || (strstr (inst, "fs:") == 0))
  1297.          && ((a_tss.tss_gs == a_tss.tss_cs) || (a_tss.tss_gs == a_tss.tss_ss)
  1298.             || (strstr (inst, "gs:") == 0)))
  1299.       refmem = 0;
  1300.       if (refmem)
  1301.     user_screen ();
  1302.       go (0);
  1303.       a_tss.tss_eflags &= ~0x0100;
  1304.       break;
  1305.     case 1: /* "Step Over" */
  1306.       user_screen ();
  1307.       step_over (&terminated, &int03hit, len);
  1308.       break;
  1309.     case 2: /* "Run" */
  1310.       user_screen ();
  1311.       if (get_breakpoint (BP_Code, -1, a_tss.tss_eip) != -1)
  1312.         trace_over_bp ();
  1313.       go_til_true_stop (&terminated, &int03hit);
  1314.       break;
  1315.     case 3: /* "Run to '_main'" */
  1316.       b = set_breakpoint (BP_Code, 0, main_entry);
  1317.       user_screen ();
  1318.       go_til_true_stop (&terminated, &int03hit);
  1319.       reset_breakpoint (b);
  1320.       break;
  1321.   }
  1322.   a_tss.tss_eflags &= ~0x0100;  /* Clear TF, in case it's set by Ctrl-C */
  1323.                 /* (in remote debugging.)               */
  1324.   code_pane_goto (a_tss.tss_eip);
  1325.   debug_screen ();
  1326.   if (kind)
  1327.     re_start_transfer ();
  1328.   redraw (0);
  1329.   first_step = 0;
  1330.   i = a_tss.tss_irqn;
  1331.  
  1332.   if (terminated)
  1333.   { message (CL_Msg, "Program terminated normally, exit code is %d",
  1334.         (word8)a_tss.tss_eax);
  1335.   } else 
  1336.   if (i == 1 || int03hit)
  1337.   { int no;
  1338.  
  1339.     no = -1;
  1340.     for (b = 0; no == -1 && b <= 3; b++)
  1341.       if ((edi.dr[6] & (1 << b)) && (edi.dr[7] & (3 << (b * 2))))
  1342.         no = b;
  1343.     if (no != -1)
  1344.       no = get_breakpoint ((edi.dr[7] >> (16 + 4 * no)) & 3,
  1345.                            ((edi.dr[7] >> (18 + 4 * no)) & 3) + 1,
  1346.                            edi.dr[no] - edi.app_base);
  1347.     else if (int03hit)
  1348.       no = get_breakpoint (BP_Code, -1, a_tss.tss_eip);
  1349.     if (no == -1)
  1350.       if (i == 1)
  1351.         no = get_breakpoint(BP_Code, -1, a_tss.tss_eip);
  1352.     if ((no != -1) && (kind > 0))
  1353.     { message (CL_Info, "%s %s breakpoint at %08lx triggered.",
  1354.                (breakpoint_table[no].sub_type == 0) ? "Normal" :
  1355.                 ((breakpoint_table[no].sub_type == 1) ? "Count-down" :
  1356.                  "Conditional"),
  1357.                (breakpoint_table[no].type == BP_Code) ? "code" :
  1358.                 ((breakpoint_table[no].type == BP_Write) ? "data write" :
  1359.                  "data read/write"),
  1360.                breakpoint_table[no].addr);
  1361.     }
  1362.   } else 
  1363.   { if (i == 0x79)
  1364.       message (CL_Info, "Keyboard interrupt");
  1365.     else if (i == 0x09)
  1366.       message (CL_Info, "Ctrl-C pressed (exception 0x09)");
  1367.     else if (i == 0x75)
  1368.     { char *reason;
  1369.     
  1370.       save_npx ();
  1371.       if ((npx.status & 0x0241) == 0x0241)
  1372.         reason = "stack overflow";
  1373.       else if ((npx.status & 0x0241) == 0x0041)
  1374.         reason = "stack underflow";
  1375.       else if (npx.status & 1)
  1376.         reason = "invalid operation";
  1377.       else if (npx.status & 2)
  1378.         reason = "denormal operand";
  1379.       else if (npx.status & 4)
  1380.         reason = "divide by zero";
  1381.       else if (npx.status & 8)
  1382.         reason = "overflow";
  1383.       else if (npx.status & 16)
  1384.         reason = "underflow";
  1385.       else if (npx.status & 32)
  1386.         reason = "loss of precision";
  1387.       else
  1388.         reason = "?";
  1389.       message (CL_Error,
  1390.         "Numeric Exception (%s) at eip=0x%08lx", reason, npx.eip);
  1391.       load_npx ();
  1392.     }
  1393.     else if (i == 8 || (i >= 10 && i <= 14))
  1394.       message (CL_Error, "Exception %d (0x%02x) occurred, error code=%#lx",
  1395.                i, i, a_tss.tss_error);
  1396.     else
  1397.       message (CL_Error, "Exception %d (0x%02x) occurred", i, i);
  1398.   }
  1399. }
  1400. /* ---------------------------------------------------------------------- */
  1401. static void
  1402. draw_debug_frames (void)
  1403. { frame (0, 1, main_x1, toplines + 1, active_pane_name);
  1404.   frame (main_x2, 1, cols - 1, toplines + 1, 0);
  1405.   frame (main_x1, 1, main_x2, toplines + 1, 0);
  1406.   frame (main_x3, toplines + 1, cols - 1, rows - 2, 0);
  1407.   frame (0, toplines + 1, main_x3, rows - 2, 0);
  1408.  
  1409.   if (!using_com_port_num)
  1410.   { put (main_x2, 1, "┬");
  1411.     put (main_x2, toplines + 1, "┴");
  1412.     put (0, toplines + 1, "├");
  1413.     put (cols - 1, toplines + 1, "┤");
  1414.     put (main_x1, 1, "┬");
  1415.     put (main_x1, toplines + 1, "┴");
  1416.     put (main_x3, toplines + 1, "┬");
  1417.     put (main_x3, rows - 2, "┴");
  1418.   }
  1419. }
  1420. /* ---------------------------------------------------------------------- */
  1421. static void
  1422. draw_focused_frame (void)
  1423. { int x1, x2, y1, y2;
  1424.  
  1425.   screen_attr = screen_attr_ffocus;
  1426.   switch (pane)    /* Set focused pane */
  1427.   { case 1:        /* Top middle */
  1428.       x1 = main_x1;
  1429.       x2 = main_x2;
  1430.       y1 = 1;
  1431.       y2 = toplines + 1;
  1432.       break;
  1433.     case 2:        /* Top right */
  1434.       x1 = main_x2;
  1435.       x2 = cols - 1;
  1436.       y1 = 1;
  1437.       y2 = toplines + 1;
  1438.       break;
  1439.      case 3:        /* Bottom right */
  1440.       x1 = main_x3;
  1441.       x2 = cols - 1;
  1442.       y1 = toplines + 1;
  1443.       y2 = rows - 2;
  1444.       break;
  1445.      case 4:        /* Bottom left */
  1446.       x1 = 0;
  1447.       x2 = main_x3;
  1448.       y1 = toplines + 1;
  1449.       y2 = rows - 2;
  1450.       break;
  1451.     default:       /* Top left */
  1452.       x1 = 0;
  1453.       x2 = main_x1;
  1454.       y1 = 1;
  1455.       y2 = toplines + 1;
  1456.       break;
  1457.   }
  1458.   if (pane < 1 || pane > 4)
  1459.     double_frame (x1, y1, x2, y2, active_pane_name);
  1460.   else
  1461.     double_frame (x1, y1, x2, y2, 0);
  1462.   screen_attr = screen_attr_normal;
  1463. }          
  1464. /* ---------------------------------------------------------------------- */
  1465. static void
  1466. put_redraw (int x, int y, int width, int max_y, int offset, char *buf)
  1467. { int buflen;
  1468.   buflen = strlen (buf);
  1469.   if (y <= max_y)
  1470.     putl (x, y, width, buf + ((offset < buflen) ? offset : buflen));
  1471. }
  1472. /* ---------------------------------------------------------------------- */
  1473. void
  1474. redraw_registers (char *buf)
  1475. { int reg, x = main_x1 + 1, y = 2, width = main_x2 - main_x1 - 1;
  1476.  
  1477.   for (reg = reg_pane_origin; regs_type[reg]; reg++)
  1478.   { if (regs_type[reg] == 's')
  1479.       sprintf (buf, " %s %04x",  regs_names[reg],
  1480.                *(unsigned short *)(regs_addr[reg]));
  1481.     else
  1482.       sprintf (buf, "%s %08lx", regs_names[reg], *(regs_addr[reg]));     
  1483.     put_redraw (x, y++, width, toplines,
  1484.                 pane_offset[REGISTER_PANE_NUM], buf);
  1485.     if (y > toplines)
  1486.       break;
  1487.   }
  1488.   while (y <= toplines)
  1489.     putl (x, y++, width, " ");
  1490.   if (pane == REGISTER_PANE_NUM)
  1491.   { screen_attr = screen_attr_focus;
  1492.     if (pane_pos >= toplines - 1)
  1493.       pane_pos = toplines - 2;
  1494.     highlight (main_x1 + 1, pane_pos + 2,
  1495.                main_x2 - main_x1 - 1);
  1496.     screen_attr = screen_attr_normal;
  1497.   }
  1498. }
  1499. /* ---------------------------------------------------------------------- */
  1500. void
  1501. redraw_flags (char *buf)
  1502. { int f, x = main_x2 + 1, y = 2, width = cols - main_x2 - 2;
  1503.   static char flags[] = "c?p?a?zn?ido????";
  1504.  
  1505.   for (f = flag_pane_origin; flags[f]; f++)
  1506.   { if (flags[f] != '?')
  1507.     { sprintf (buf, "%c=%d", flags[f], (int)((a_tss.tss_eflags >> f) & 1));
  1508.       put_redraw (x, y++, width, toplines, pane_offset[FLAG_PANE_NUM], buf);
  1509.     }
  1510.     if (y > toplines)
  1511.       break;
  1512.   }
  1513.   while (y <= toplines)
  1514.     putl (x, y++, width, " ");
  1515.   if (pane == FLAG_PANE_NUM)
  1516.   { screen_attr = screen_attr_focus;
  1517.     if (pane_pos >= toplines - 1)
  1518.       pane_pos = toplines - 2;
  1519.     highlight (main_x2 + 1, pane_pos + 2,
  1520.                cols - main_x2 - 2);
  1521.     screen_attr = screen_attr_normal;
  1522.   }
  1523. }
  1524. /* ---------------------------------------------------------------------- */
  1525. void
  1526. redraw_breakpoints (char *buf)
  1527. { int b, x = main_x3 + 1, y = toplines + 2, width = cols - main_x3 - 2;
  1528.   char *name;
  1529.   int32 delta;
  1530.  
  1531.   for (b = breakpoint_origin;
  1532.        b < breakpoint_origin + bottomlines / 2 && b < breakpoint_count;
  1533.        b++)
  1534.   { switch (breakpoint_table[b].type)
  1535.     { case BP_Code:
  1536.         sprintf (buf, "%-20s", "C ");
  1537.         break;
  1538.       case BP_Write:
  1539.         sprintf (buf, "%-20s, %d","DW",
  1540.                  breakpoint_table[b].length);
  1541.         break;
  1542.       case BP_Read:
  1543.         sprintf (buf, "%-20s, %d","DR",
  1544.                  breakpoint_table[b].length);
  1545.         break;
  1546.     }    
  1547.     switch (breakpoint_table[b].sub_type)
  1548.     { case 0:
  1549.         sprintf (buf + 3, "Norm.");
  1550.         break;
  1551.       case 1:
  1552.         sprintf (buf + 3, "Count");
  1553.         break;
  1554.       case 2:
  1555.         sprintf (buf + 3, "Cond.");
  1556.         break;
  1557.     }
  1558.     buf[8] = ' ';
  1559.     putl (x, y, width, buf);
  1560.     screen_attr = screen_attr_addr;
  1561.     sprintf(buf, "%08lx", breakpoint_table[b].addr);
  1562.     if (width > 12)
  1563.       putl(x + 12, y, width - 12 > 8 ? 8 : width - 12, buf);
  1564.     y++;
  1565.     screen_attr = screen_attr_normal;
  1566.     name = syms_val2name (breakpoint_table[b].addr, &delta);
  1567.     if (name[0] != '0')
  1568.       if (delta && strlen (name) < width)
  1569.         sprintf (buf, " %s+%#lx", name, delta);
  1570.       else
  1571.         sprintf (buf, " %-*s", width, name);
  1572.     else
  1573.       buf[0] = '\0';      
  1574.     put_redraw (x, y++, width, rows,
  1575.                 pane_offset[BREAKPOINT_PANE_NUM], buf);
  1576.   }
  1577.   if (breakpoint_count == 0)
  1578.     putl (x, y++, width, "No breakpoints");
  1579.   while (y < rows - 2)
  1580.     putl (x, y++, width, "");
  1581.   if (pane == BREAKPOINT_PANE_NUM)
  1582.   { screen_attr = screen_attr_focus;
  1583.     if (breakpoint_origin >= breakpoint_count)
  1584.       breakpoint_origin = breakpoint_count ? breakpoint_count - 1 : 0;
  1585.     if (breakpoint_origin + pane_pos >= breakpoint_count)
  1586.       pane_pos = breakpoint_count - breakpoint_origin;
  1587.     if (2 * pane_pos + 2 > bottomlines)
  1588.       pane_pos = bottomlines / 2 - 1;
  1589.     if (pane_pos < 0)
  1590.       pane_pos = 0;
  1591.     else
  1592.     { highlight (main_x3 + 1, toplines + 2 + 2 * pane_pos, 
  1593.                  cols - main_x3 - 2);
  1594.       if (2 * pane_pos + 1 < bottomlines)
  1595.         highlight (main_x3 + 1, toplines + 3 + 2 * pane_pos,
  1596.                    cols - main_x3 - 2);
  1597.     }
  1598.     screen_attr = screen_attr_normal;
  1599.   }
  1600. }
  1601. /* ---------------------------------------------------------------------- */
  1602. void
  1603. redraw_data (char *buf)
  1604. { word32 p = data_dump_origin;
  1605.   int b, x, y = toplines + 2, ok, width = main_x3 - 1;
  1606.   unsigned char data[8], xpos[8];
  1607.   int buflen;
  1608.  
  1609.   for (x = 0; x < 8; x++)
  1610.     xpos[x] = 1 + ((data_dump_size == 1) ? (x * 3) :
  1611.         ((data_dump_size == 2) ? ((x / 2) * 5 + (~x & 1) * 2) :
  1612.          ((x / 4) * 9 + (~x & 3) * 2)));
  1613.   while (y < rows - 2)
  1614.   { if ((ok = valid_addr (p, 8)))
  1615.       read_child (p, data, 8);
  1616.  
  1617.     screen_attr = screen_attr_addr;
  1618.     sprintf (buf, "%08lx:",p);
  1619.     putl (1, y, 9, buf);
  1620.     sprintf (buf, "%70s", " ");
  1621.     for (x = 0; x < 8; x++)
  1622.       if (ok || valid_addr (p + x, 1))
  1623.       { if (!ok) 
  1624.           read_child (p + x, data + x, 1);
  1625.         buf[xpos[x]] = hexchars[data[x] >> 4];
  1626.         buf[xpos[x] + 1] = hexchars[data[x] & 0xf];
  1627.         buf[28 + x] = (data[x] ? data[x] : '.');
  1628.       } else
  1629.         buf[xpos[x]] = buf[xpos[x + 1]] = buf[28 + x] = '?';
  1630.     screen_attr = screen_attr_normal;                                   
  1631.     buflen = strlen (buf);
  1632.     putl (10, y, width - 9, buf + ((pane_offset[DATA_PANE_NUM] < buflen)
  1633.                                   ? pane_offset[DATA_PANE_NUM] : buflen));
  1634.     screen_attr = screen_attr_break;
  1635.     for (x = 0; x < 8; x++)
  1636.       for (b = 0; b < breakpoint_count; b++)
  1637.         if (breakpoint_table[b].type != BP_Code
  1638.             && p + x >= breakpoint_table[b].addr
  1639.             && p + x < (breakpoint_table[b].addr
  1640.                       + breakpoint_table[b].length))
  1641.            { if (xpos[x] >= pane_offset[DATA_PANE_NUM])
  1642.                highlight (xpos[x] + 10 - pane_offset[DATA_PANE_NUM], y, 2);
  1643.              if (x + 28 >= pane_offset[DATA_PANE_NUM])
  1644.                highlight (38 + x - pane_offset[DATA_PANE_NUM], y, 1);
  1645.            }
  1646.     screen_attr = screen_attr_normal;
  1647.     p += 8;
  1648.     y++;
  1649.   }
  1650.   data_dump_last = p - 1;
  1651.   if (pane == DATA_PANE_NUM)
  1652.   { int offset;
  1653.     int x = pane_pos & 7, y = pane_pos >> 3;
  1654.  
  1655.     while (y >= bottomlines)
  1656.     { y--;
  1657.       pane_pos -= 8;
  1658.     }
  1659.     screen_attr = screen_attr_focus;
  1660.     if ((38 + x + data_dump_size <= main_x3) &&
  1661.        (x + 28 >= pane_offset[INFO_PANE_NUM]))
  1662.        highlight (38 + x - pane_offset[DATA_PANE_NUM], 
  1663.                   toplines + 2 + y, data_dump_size);
  1664.     switch (data_dump_size)
  1665.     { case 1:  
  1666.         offset = 1 + 3 * x - pane_offset[DATA_PANE_NUM];
  1667.         if (13 + 3 * x <= main_x3)
  1668.           if (offset >= 0)
  1669.             highlight (11 + 3 * x - pane_offset[DATA_PANE_NUM], 
  1670.                        toplines + 2 + y, 2);
  1671.           else if (offset > -1)
  1672.             highlight (10, toplines + 2 + y, 2 + offset);
  1673.         break;
  1674.       case 2:
  1675.         offset = 1 + 5 * (x >> 1) - pane_offset[DATA_PANE_NUM];
  1676.         if (15 + 5 * (x >> 1) <= main_x3)
  1677.           if (offset >= 0)
  1678.             highlight (11 + 5 * (x >> 1) - pane_offset[DATA_PANE_NUM], 
  1679.                        toplines + 2 + y, 4);
  1680.           else if (offset > -4)
  1681.             highlight (10, toplines + 2 + y, 4 + offset);
  1682.         break;
  1683.       case 4:
  1684.         offset = 1 + 9 * (x >> 2) - pane_offset[DATA_PANE_NUM];
  1685.         if (19 + 9 * (x >> 2) <= main_x3)
  1686.           if (offset >= 0)
  1687.             highlight (11 + 9 * (x >> 2) - pane_offset[DATA_PANE_NUM], 
  1688.                        toplines + 2 + y, 8);
  1689.           else if (offset > -8)
  1690.             highlight (10, toplines + 2 + y, 8 + offset);
  1691.         break;
  1692.     }
  1693.     screen_attr = screen_attr_normal;
  1694.   }
  1695. }
  1696. /* ---------------------------------------------------------------------- */
  1697. void
  1698. redraw_code (char *buf)
  1699. { word32 p = code_dump_origin, width = main_x1 - 1;
  1700.   int y = 2, len, source = 0, buflen;
  1701.   char *txt;
  1702.  
  1703.   while (y <= toplines)
  1704.   { source = !source;
  1705.     code_pane_pos[y - 2] = p;
  1706.     if (source)
  1707.     { txt = unassemble_source (p);
  1708.       if (txt)
  1709.       { screen_attr = screen_attr_source;
  1710.         buflen = strlen (txt);
  1711.         putl (1, y++, width, txt + ((pane_offset[CODE_PANE_NUM] < buflen)
  1712.                                    ? pane_offset[CODE_PANE_NUM] : buflen));
  1713.       }
  1714.     }    else
  1715.     { int temp_len;
  1716.  
  1717.       if (valid_instaddr (p))
  1718.         txt = unassemble_proper (p, &len);
  1719.       else
  1720.         txt = "?", len = 1;
  1721.       sprintf (buf, "%08lx%c", p, p == a_tss.tss_eip ? '>' : ' ');
  1722.       screen_attr = (get_breakpoint (BP_Code, -1, p) == -1
  1723.                     ? screen_attr_addr : screen_attr_break);
  1724.       temp_len = strlen(buf);
  1725.       putl (1, y++, (width > temp_len ? temp_len : width), buf);
  1726.       if (width > temp_len)
  1727.       { screen_attr = (get_breakpoint (BP_Code, -1, p) == -1
  1728.                       ? screen_attr_asm : screen_attr_break);
  1729.         buflen = strlen (txt);
  1730.         putl(temp_len + 1,y - 1,(width - temp_len),
  1731.              txt + ((pane_offset[CODE_PANE_NUM] < buflen)
  1732.                    ? pane_offset[CODE_PANE_NUM] : buflen));
  1733.       }
  1734.       p += len;
  1735.     }
  1736.   }
  1737.   code_pane_pos[y - 2] = p + 1;
  1738.   code_dump_last = p - 1;
  1739.   if (pane == CODE_PANE_NUM)
  1740.   { screen_attr = screen_attr_focus;
  1741.     if (pane_pos >= toplines - 1)
  1742.       pane_pos = toplines - 2;
  1743.     highlight (1, pane_pos + 2, main_x1 - 1);
  1744.   }
  1745.   screen_attr = screen_attr_normal;
  1746. }
  1747. /* ---------------------------------------------------------------------- */
  1748. void
  1749. redraw_npx (char *buf)
  1750. { int i, y = 2, width = main_x1 - 1;
  1751.   static char *rtype[] = { "Near", "-Inf", "+Inf", "Zero" };
  1752.  
  1753.   save_npx ();
  1754.   sprintf (buf,
  1755.            "Control: %04lx PR=%s UN=%s OV=%s ZD=%s DN=%s IV=%s Rnd=%s",
  1756.            npx.control & 0xffff,
  1757.            (npx.control & (1 << 5)) ? "N" : "Y",
  1758.            (npx.control & (1 << 4)) ? "N" : "Y",
  1759.            (npx.control & (1 << 3)) ? "N" : "Y",
  1760.            (npx.control & (1 << 2)) ? "N" : "Y",
  1761.            (npx.control & (1 << 1)) ? "N" : "Y",
  1762.            (npx.control & (1 << 0)) ? "N" : "Y",
  1763.            rtype[(npx.control >> 10) & 3]);
  1764.   put_redraw (1, y++, width, toplines, pane_offset[NPX_PANE_NUM], buf);
  1765.   sprintf (buf,
  1766.            "Status:  %04lx PR=%s UN=%s OV=%s ZD=%s DN=%s IV=%s ST=%s",
  1767.            npx.status & 0xffff,
  1768.            (npx.status & (1 << 5)) ? "Y" : "N",
  1769.            (npx.status & (1 << 4)) ? "Y" : "N",
  1770.            (npx.status & (1 << 3)) ? "Y" : "N",
  1771.            (npx.status & (1 << 2)) ? "Y" : "N",
  1772.            (npx.status & (1 << 1)) ? "Y" : "N",
  1773.            (npx.status & (1 << 0)) ? "Y" : "N",
  1774.            (npx.status & (1 << 6)) ? "Y" : "N");
  1775.   put_redraw (1, y++, width, toplines, pane_offset[NPX_PANE_NUM], buf);
  1776.   sprintf (buf, "%19sC3=%d C2=%d C1=%d C0=%d",
  1777.            "",
  1778.            (npx.status & (1 << 14)) != 0,
  1779.            (npx.status & (1 << 10)) != 0,
  1780.            (npx.status & (1 <<  9)) != 0,
  1781.            (npx.status & (1 <<  8)) != 0);
  1782.   put_redraw (1, y++, width, toplines, pane_offset[NPX_PANE_NUM], buf);
  1783.   for (i = 0; i < 8; i++)
  1784.   {
  1785. /* ---------------------------------------------------------------------
  1786.    -     We assume that `long double' is the same type as npx.reg[i].
  1787.    -     It would be sensible to check that the sizes match, but they
  1788.    -     don't!  For alignment reasons, `sizeof (long double)' is 12.  
  1789.    ---------------------------------------------------------------------*/
  1790.       long double d;
  1791.       int tag;
  1792.       int tos = (npx.status >> 11) & 7;
  1793.       int exp = (int)npx.reg[i].exponent - 16382;
  1794.       char *dstr = alloca (30);
  1795.  
  1796.       dstr[0] = (npx.reg[i].sign) ? '-' : '+';
  1797.       dstr[1] = '\0';
  1798.       tag = (npx.tag >> (((i + tos) & 7) * 2)) & 3;
  1799.       switch (tag)
  1800.       { case 0:
  1801.           if (abs (exp) < 1000)
  1802.           { d = *((long double*)(npx.reg + i));
  1803. /* --------------------------------------------------------------------
  1804.    -  sprintf does not (djgpp 1.11m3) handle long doubles.  
  1805.    -------------------------------------------------------------------- */
  1806.             sprintf(dstr,"%+.16g", (double) d);
  1807.           } else
  1808.             sprintf (dstr, "Valid, %s, and %s",
  1809.                      npx.reg[i].sign ? "negative" : "positive",
  1810.                      exp > 0 ? "huge" : "tiny");
  1811.           break;
  1812.         case 1:
  1813.           strcat (dstr, "Zero");
  1814.           break;
  1815.         case 2:
  1816.           if (npx.reg[i].exponent == 0x7fff)
  1817.             if (npx.reg[i].sig3 == 0x8000 && npx.reg[i].sig2 == 0x0000
  1818.               && npx.reg[i].sig1 == 0x0000  && npx.reg[i].sig0 == 0x0000)
  1819.               strcat (dstr, "Inf");
  1820.             else
  1821.               strcat (dstr, "NaN");
  1822.           else
  1823.             sprintf (dstr, "Special");
  1824.           break;
  1825.         case 3:
  1826.           sprintf (dstr, "Empty");
  1827.           break;
  1828.       }
  1829.       sprintf (buf, "st(%d): %d %04x %04x%04x%04x%04x %s",
  1830.                i,
  1831.                npx.reg[i].sign, npx.reg[i].exponent,
  1832.                npx.reg[i].sig3, npx.reg[i].sig2,
  1833.                npx.reg[i].sig1, npx.reg[i].sig0,
  1834.                dstr);
  1835.       put_redraw (1, y++, width, toplines,
  1836.                   pane_offset[NPX_PANE_NUM], buf);
  1837.       if (y > toplines)
  1838.         break;
  1839.   }
  1840.   while (y <= toplines)
  1841.     putl (1, y++, width, " ");
  1842.   load_npx ();
  1843.   if (pane == NPX_PANE_NUM)
  1844.   { screen_attr = screen_attr_focus;
  1845.     if (pane_pos >= toplines - 1)
  1846.       pane_pos = toplines - 2;
  1847.     highlight (1, pane_pos + 2, main_x1 - 1);
  1848.     screen_attr = screen_attr_normal;
  1849.   }
  1850. }
  1851. /* ---------------------------------------------------------------------- */
  1852. void
  1853. redraw_stack (char *buf)
  1854. { int line, y = 2, no = -stack_dump_origin, width = main_x1 - 1;
  1855.   unsigned char eipcode[4];
  1856.   word32 delta, v = a_tss.tss_ebp;
  1857.   word32 vaddr = a_tss.tss_eip;
  1858.   int first = 1;
  1859.  
  1860.   stack_dump_more = 0;
  1861.   while (valid_instaddr (vaddr))
  1862.   { if (no++ >= 0)
  1863.       if (y >= toplines)
  1864.       { stack_dump_more = 1;
  1865.         break;
  1866.       } else
  1867.       { char *symaddr, *sourceaddr, *sourcefile;
  1868.         int len;
  1869.         char *mybuf;
  1870.         
  1871.         symaddr = syms_val2name (vaddr, &delta);
  1872.         sourcefile = syms_val2line (vaddr, &line, 0);
  1873.         if (sourcefile)
  1874.           sprintf (sourceaddr = alloca (cols + strlen (sourcefile)),
  1875.                    ", line %d in file %s", line, sourcefile);
  1876.         else if (delta)
  1877.           sprintf (sourceaddr = alloca (cols), "%+ld", (long) delta);
  1878.         else
  1879.           sourceaddr = "";
  1880.         len = 15 + strlen (symaddr) + strlen (sourceaddr);
  1881.         mybuf = alloca (len + 15);
  1882.         sprintf (mybuf, "%08lx: %s%s", vaddr, symaddr, sourceaddr);
  1883.         stack_dump_last = (y - 2) / 2;
  1884.         stack_dump_pos[stack_dump_last] = vaddr;
  1885.         put_redraw (1, y++, width, toplines,
  1886.                     pane_offset[STACK_PANE_NUM], mybuf);
  1887.         sprintf (mybuf, "   Stack frame: %08lx", v);
  1888.         put_redraw (1, y++, width, toplines,
  1889.                     pane_offset[STACK_PANE_NUM], mybuf);
  1890.       }
  1891.     if (first)
  1892.     { first = 0;
  1893.       read_child (vaddr, eipcode, 3);
  1894. /* ---------------------------------------------------------------------
  1895.    - We look directly at the bit pattern instead of using disassembly;
  1896.    - the bit patterns are those generated by gcc.  In general we
  1897.    - cannot expect to be able to follow a non-gcc stack anyway.  
  1898.    --------------------------------------------------------------------- */
  1899.       if ((eipcode[0] == 0x55 && eipcode[1] == 0x89 && eipcode[2] == 0xe5)
  1900.           || eipcode[0] == 0xc3)
  1901.       {
  1902. /* ---------------------------------------------------------------------
  1903.    - In this case where we are looking at `Push Ebp//Mov Ebp,Esp'
  1904.    - or `Ret', only the return address is on the stack; I believe
  1905.    - this only to happen in the innermost activation record.  
  1906.    --------------------------------------------------------------------- */
  1907.         if (valid_addr (a_tss.tss_esp, 4))
  1908.           read_child (a_tss.tss_esp, &vaddr, 4);
  1909.         else
  1910.           break;
  1911.       } else
  1912.       { if (eipcode[0] == 0x89 && eipcode[1] == 0xe5)
  1913. /* ---------------------------------------------------------------------
  1914.    - When looking at `Mov Esp,Ebp' the next stack frame is on
  1915.    - the stack and pointed to by the stack pointer.  We are
  1916.    - actually in the same situation after `Mov Esp,Ebp' which
  1917.    - is generated by gcc with the -m486 option.  This case is,
  1918.    - however, handled perfectly by using the base pointer.  
  1919.    --------------------------------------------------------------------- */
  1920.           v = a_tss.tss_esp;
  1921.         if (v >= a_tss.tss_esp && v < 0x80000000L && valid_addr (v, 8))
  1922.         { read_child (v + 4, &vaddr, 4);
  1923.           read_child (v, &v, 4);
  1924.         } else
  1925.           break;
  1926.       }
  1927.     } else
  1928.     { if (v >= a_tss.tss_esp && v < 0x80000000L && valid_addr (v, 8))
  1929.       { read_child (v + 4, &vaddr, 4);
  1930.         read_child (v, &v, 4);
  1931.       } else
  1932.         break;
  1933.     }
  1934.   }
  1935.   while (y <= toplines)
  1936.     putl (1, y++, width, " ");
  1937.   if (pane == STACK_PANE_NUM)
  1938.   { screen_attr = screen_attr_focus;
  1939.     if (pane_pos * 2 + 2 > toplines - 1)
  1940.       pane_pos = (toplines - 1) / 2 - 1;
  1941.     if (pane_pos < 0)
  1942.       pane_pos = 0;
  1943.     else
  1944.     { if (pane_pos > stack_dump_last)
  1945.         pane_pos = stack_dump_last;
  1946.       highlight (1, pane_pos * 2 + 2, main_x1 - 1);
  1947.     }
  1948.     screen_attr = screen_attr_normal;
  1949.   }
  1950. }
  1951. /* ---------------------------------------------------------------------- */
  1952. void
  1953. redraw_info (char *buf)
  1954. { int y = 2, width = main_x1 - 1;
  1955.   long ul;
  1956.   char *s = alloca (20);
  1957.   _go32_dpmi_meminfo info;
  1958.   _go32_dpmi_registers regs;
  1959.  
  1960.   sprintf (buf, "Debugger version ............: %d.%02d %s",
  1961.        MAJOR_VER, MINOR_VER,
  1962.        MAJOR_VER == 0 ? "beta" : "");
  1963.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  1964.   _go32_dpmi_get_free_memory_information (&info);
  1965.   switch (_go32_info_block.run_mode)
  1966.   { case _GO32_RUN_MODE_RAW:
  1967.       sprintf (s, "Raw");
  1968.       break;
  1969.     case _GO32_RUN_MODE_XMS:
  1970.       sprintf (s, "Xms");
  1971.       break;
  1972.     case _GO32_RUN_MODE_VCPI:
  1973.       sprintf (s, "Vcpi");
  1974.       break;
  1975.     case _GO32_RUN_MODE_DPMI:
  1976.       sprintf (s, "Dpmi %d.%02x",
  1977.            _go32_info_block.run_mode_info >> 8,
  1978.            _go32_info_block.run_mode_info & 0xff);
  1979.       break;
  1980.     default:
  1981.       sprintf (s, "Unknown");
  1982.   }
  1983.   sprintf (buf, "Running mode ................: %s", s);
  1984.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  1985.   if (y <= toplines)
  1986.     putl (1, y++, width, "");
  1987.  
  1988.   ul = info.total_physical_pages;
  1989.   if (ul > 0)
  1990.   { ul <<= 12;
  1991.     sprintf (buf, "Total physical memory .......: %lu KB", ul >> 10);
  1992.     put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  1993.   }
  1994.   ul = info.available_physical_pages
  1995.     ? info.available_physical_pages << 12
  1996.     : info.available_memory;
  1997.   sprintf (buf, "Remaining physical memory ...: %lu KB", ul >> 10);
  1998.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  1999.   ul = info.available_memory;
  2000.   sprintf (buf, "Remaining virtual memory ....: %lu KB", ul >> 10);
  2001.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  2002.   ul = info.free_linear_space << 12;
  2003.   if (ul >= 0)
  2004.   { sprintf (buf, "Free linear space ...........: %ld KB", ul >> 10);
  2005.     put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  2006.   }
  2007. /* ----------------------------------------------------------------
  2008.    - Remember that Dos memory is only made available of direct request;
  2009.    - using 0xffff does not count as a request.  
  2010.    ---------------------------------------------------------------- */
  2011.   regs.h.ah = 0x48;
  2012.   regs.x.bx = 0xffff;
  2013.   regs.x.ss = regs.x.sp = 0;                        
  2014. /* ----------------------------------------------------------
  2015.    -  The call _go32_dpmi_simulate_int () causes the program 
  2016.    -  to hang under XMS mode.
  2017.    ---------------------------------------------------------- */
  2018.   if (_go32_info_block.run_mode != _GO32_RUN_MODE_XMS)
  2019.     _go32_dpmi_simulate_int (0x21, ®s);
  2020.   ul = regs.x.bx << 4;
  2021.   sprintf (buf, "Free dos memory .............: %ld %s",
  2022.            ul > 8192 ? ul >> 10 : ul,
  2023.            ul > 8192 ? "KB"     : "Bytes");
  2024.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  2025.   if (y <= toplines)
  2026.     putl (1, y++, width, "");
  2027.   sprintf (buf, "Ctrl-C checking .............: %s",
  2028.           getcbrk () ? "On" : "Off");
  2029.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  2030.   if (y <= toplines)
  2031.     putl (1, y++, width, "");
  2032.  
  2033.   sprintf (buf, "Program text ................: %08lx - %08lx",
  2034.            areas[A_text].first_addr, areas[A_text].last_addr);
  2035.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  2036.   sprintf (buf, "Program data ................: %08lx - %08lx",
  2037.            areas[A_data].first_addr, areas[A_data].last_addr);
  2038.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  2039.   sprintf (buf, "Program bss .................: %08lx - %08lx",
  2040.            areas[A_bss].first_addr, areas[A_bss].last_addr);
  2041.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  2042.   sprintf (buf, "Program stack ...............: %08lx - %08lx",
  2043.            areas[A_stack].first_addr, areas[A_stack].last_addr);
  2044.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  2045.   if (y <= toplines)
  2046.     putl (1, y++, width, "");
  2047.   sprintf (buf, "Using com port number .......: %d",
  2048.            using_com_port_num);
  2049.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  2050.   sprintf (buf, "Using symbol file ...........: %s%s.%s",
  2051.            sympath, symname, symext);
  2052.   put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
  2053.   while (y <= toplines)
  2054.     putl (1, y++, width, " ");
  2055. }
  2056. /* ---------------------------------------------------------------------- */
  2057. void
  2058. redraw_whereis (char *buf)
  2059. { int y = 2, width = main_x1 - 1, i = whereis_origin;
  2060.   char *s;
  2061.  
  2062.   while (y <= toplines)
  2063.     if (i < whereis_sym_count)
  2064.     { s = syms_makewild (whereis_pane_sym[i++]);
  2065.       put_redraw (1, y++, width, toplines,
  2066.                   pane_offset[WHEREIS_PANE_NUM], s);
  2067.     } else
  2068.       putl (1, y++, width, " ");
  2069.   if (pane == WHEREIS_PANE_NUM)
  2070.   { screen_attr = screen_attr_focus;
  2071.     if (pane_pos >= toplines - 1)
  2072.       pane_pos = toplines - 2;
  2073.     if (whereis_sym_count)
  2074.       highlight (1, pane_pos + 2, main_x1 - 1);
  2075.     screen_attr = screen_attr_normal;
  2076.   }
  2077. }
  2078. /* ---------------------------------------------------------------------- */
  2079. void
  2080. redraw_module (char *buf)
  2081. { int y = 2, width = main_x1 - 1, i = module_origin;
  2082.  
  2083.   while (y <= toplines)
  2084.     if (i < module_text_count)
  2085.       put_redraw (1, y++, width, toplines,
  2086.                   pane_offset[MODULE_PANE_NUM], module_pane_text[i++]);
  2087.     else
  2088.       putl (1, y++, width, " ");
  2089.   if (pane == MODULE_PANE_NUM)
  2090.   { screen_attr = screen_attr_focus;
  2091.     if (pane_pos >= toplines - 1)
  2092.       pane_pos = toplines - 2;
  2093.     if (module_text_count)
  2094.       highlight (1, pane_pos + 2, main_x1 - 1);
  2095.     screen_attr = screen_attr_normal;
  2096.   }
  2097. }
  2098. /* ---------------------------------------------------------------------- */
  2099. void
  2100. redraw_help (char *buf)
  2101. { int y = 2, width = main_x1 - 1, i = help_origin;
  2102.  
  2103.   while (y <= toplines)
  2104.     if (i < help_text_count)
  2105.     { screen_attr = ((*help_pane_text[i] != ' ')
  2106.             ? screen_attr_help : screen_attr_normal);
  2107.       put_redraw (1, y++, width, toplines,
  2108.                   pane_offset[HELP_PANE_NUM], help_pane_text[i++]);
  2109.     } else
  2110.       putl (1, y++, width, " ");
  2111.   if (pane == HELP_PANE_NUM)
  2112.   { screen_attr = screen_attr_focus;
  2113.     if (pane_pos >= toplines - 1)
  2114.       pane_pos = toplines - 2;
  2115.     if (help_text_count)
  2116.       highlight (1, pane_pos + 2, main_x1 - 1);
  2117.     screen_attr = screen_attr_normal;
  2118.   }
  2119. }
  2120. /* --
  2121. static char *st_fmt = "%04x %04x %04x %04x %04x %04x %08lx %08lx";
  2122.  -- */
  2123. /* ---------------------------------------------------------------------- */
  2124. void
  2125. redraw (int first)
  2126. { char *buf = alloca (1024);
  2127.  
  2128.   debug_screen ();
  2129.   screen_attr = ScreenAttrib = screen_attr_normal;
  2130.   if (first == -1)
  2131.   { screen_attr = screen_attr_resize;
  2132.     clear_screen();
  2133.   }
  2134.   draw_debug_frames ();
  2135.   if (first == -1)           /* For resizing */
  2136.   { put_screen (debug_screen_save);
  2137.     return;
  2138.   }
  2139.   draw_focused_frame ();
  2140.  
  2141.   redraw_registers (buf);
  2142.   redraw_flags (buf);
  2143.   redraw_breakpoints (buf);
  2144.   redraw_data (buf);
  2145.   if (code_pane_active)
  2146.     redraw_code (buf);
  2147.   if (npx_pane_active)
  2148.     redraw_npx (buf);
  2149.   if (stack_pane_active)
  2150.     redraw_stack (buf);
  2151.   if (info_pane_active)
  2152.     redraw_info (buf);
  2153.   if (whereis_pane_active)
  2154.     redraw_whereis (buf);
  2155.   if (module_pane_active)
  2156.     redraw_module (buf);
  2157.   if (help_pane_active)
  2158.     redraw_help (buf);
  2159.   screen_attr = st_ln_attr;
  2160.  
  2161. /* --
  2162.  asm ("push %ebp         \n\
  2163.        push %esp         \n\
  2164.        push %ss          \n\
  2165.        push %gs          \n\
  2166.        push %fs          \n\
  2167.        push %es          \n\
  2168.        push %ds          \n\
  2169.        push %cs          \n\
  2170.        push _st_fmt      \n\
  2171.        push $_StatusLine \n\
  2172.        call _sprintf     \n\
  2173.        add  $0x28, %esp  \n\
  2174.       ");
  2175.   st_fmt[0] += 0;
  2176.  -- */
  2177.  
  2178.   putl (0, rows - 1, cols, StatusLine);
  2179.   if (running_xsupport)
  2180.     redraw_xsupport (buf);
  2181.   else
  2182.     show_menu_bar (Main_Menu);
  2183.   free (buf);
  2184. }
  2185. /* ---------------------------------------------------------------------- */
  2186. static void
  2187. init_module (void)
  2188. {
  2189.   char *s;
  2190.  
  2191.   s = malloc(25);
  2192.   s = "Modules listing:";
  2193.   module_pane_text = realloc (module_pane_text,
  2194.               (++module_text_count) * sizeof (char *));
  2195.   module_pane_text[module_text_count - 1] = strdup (s);
  2196.   free(s);
  2197.   s = get_module(module_text_count - 1);
  2198.   while (!undefined_symbol)
  2199.   {
  2200.     module_pane_text = realloc (module_pane_text,
  2201.               (++module_text_count) * sizeof (char *));
  2202.     module_pane_text[module_text_count - 1] = strdup (s);
  2203.     free(s);
  2204.     s = get_module(module_text_count - 1);
  2205.   }
  2206.   undefined_symbol = 0;
  2207. }
  2208. /* ---------------------------------------------------------------------- */
  2209. static void
  2210. put_help_line(const char *str)
  2211. {
  2212.   help_pane_text = realloc (help_pane_text,
  2213.                (++help_text_count) * sizeof (char *));
  2214.   help_pane_text[help_text_count - 1] = strdup (str);
  2215.  
  2216. }
  2217. /* ---------------------------------------------------------------------- */
  2218. static void
  2219. init_help (void)
  2220. { put_help_line("----------------------------------------------------------");
  2221.   put_help_line("GLOBAL KEY BINDINGS:");
  2222.   put_help_line(" ");
  2223.   put_help_line(" C-x C-c     Quit debugger.  You will be prompted first.");
  2224.   put_help_line(" C-x C-v     Save or load debugger context.");
  2225.   put_help_line(" C-r         Run program.");
  2226.   put_help_line(" C-h         Make Help pane active.");
  2227.   put_help_line(" BS          Make Help pane active.");
  2228.   put_help_line(" C-x C-w     Write active pane contents to a file.  Only");
  2229.   put_help_line("             the visible portion of the pane is saved.");
  2230.   put_help_line(" C-x C-f     Display contents of log file.");
  2231.   put_help_line(" C-x m       Toggle between color/monochrome mode.");
  2232.   put_help_line(" C-x C-e     Evaluate an expression and display result");
  2233.   put_help_line("             in the minibuffer.");
  2234.   put_help_line(" C-z         Show program output.  Press any key to return");
  2235.   put_help_line("             to the debugger.");
  2236.   put_help_line(" C-l         Redraw the screen.");
  2237.   put_help_line(" ESC C-p <c> Goto pane whose name begins with <c>.");
  2238.   put_help_line(" C-x C-o     Toggle between insert/overstrike mode.");
  2239.   put_help_line(" ");
  2240.   put_help_line("----------------------------------------------------------");
  2241.   put_help_line("MAIN MENU:");
  2242.   put_help_line(" ");
  2243.   put_help_line(" ESC ESC     Quit main menu, go to previously active pane.");
  2244.   put_help_line(" C-g         Quit main menu, go to previously active pane.");
  2245.   put_help_line(" f           Select File pulldown.");
  2246.   put_help_line(" p           Select Pane pulldown.");
  2247.   put_help_line(" l           Select Local pulldown.");
  2248.   put_help_line(" m           Select Miscellaneous pulldown.");
  2249.   put_help_line(" h           Select Help pulldown.");
  2250.   put_help_line(" CR          Select pulldown of highlighted choice.");
  2251.   put_help_line(" DN          Select pulldown of highlighted choice.");
  2252.   put_help_line(" C-n         Select pulldown of highlighted choice.");
  2253.   put_help_line(" C-f         Highlight next choice on main menu.");
  2254.   put_help_line(" TAB         Highlight next choice on main menu.");
  2255.   put_help_line(" RT          Highlight next choice on main menu.");
  2256.   put_help_line(" C-b         Highlight previous choice on main menu.");
  2257.   put_help_line(" S-TAB       Highlight previous choice on main menu.");
  2258.   put_help_line(" LT          Highlight previous choice on main menu.");
  2259.   put_help_line(" ");
  2260.   put_help_line("----------------------------------------------------------");
  2261.   put_help_line("PULLDOWNS:");
  2262.   put_help_line(" ");
  2263.   put_help_line(" ESC ESC     Go to main menu.");
  2264.   put_help_line(" CR          Select currently highlighted pulldown item.");
  2265.   put_help_line(" C-n         Highlight next pulldown item.");
  2266.   put_help_line(" DN          Highlight next pulldown item.");
  2267.   put_help_line(" C-p         Highlight previous pulldown item.");
  2268.   put_help_line(" UP          Highlight previous pulldown item.");
  2269.   put_help_line(" C-f         Show pulldown of next main menu choice.");
  2270.   put_help_line(" RT          Show pulldown of next main menu choice.");
  2271.   put_help_line(" TAB         Show pulldown of next main menu choice.");
  2272.   put_help_line(" C-b         Show pulldown of previous main menu choice.");
  2273.   put_help_line(" LT          Show pulldown of previous main menu choice.");
  2274.   put_help_line(" S-TAB       Show pulldown of previous main menu choice.");
  2275.   put_help_line(" ");
  2276.   put_help_line("----------------------------------------------------------");
  2277.   put_help_line("PANES:");
  2278.   put_help_line(" ");
  2279.   put_help_line(" ESC ESC     Go to main menu.");
  2280.   put_help_line(" C-x o       Go forward one pane.");
  2281.   put_help_line(" TAB         Go forward one pane.");
  2282.   put_help_line(" S-TAB       Go backward one pane.");
  2283.   put_help_line(" C-x C-x     Go to previous pane (and again to return).");
  2284.   put_help_line(" C-x ^       Make current pane taller by one line.");
  2285.   put_help_line(" C-x }       Make current pane wider by one line.");
  2286.   put_help_line(" C-x >       Scroll text right (show more of the left).");
  2287.   put_help_line(" C-x <       Scroll text left (show more of the right).");
  2288.   put_help_line(" C-f         Move forward one line/byte/halfword/fullword.");
  2289.   put_help_line(" RT          Move forward one line/byte/halfword/fullword.");
  2290.   put_help_line(" C-b         Move backward one line/byte/halfword/fullword.");
  2291.   put_help_line(" LT          Move backward one line/byte/halfword/fullword.");
  2292.   put_help_line(" C-n         Move forward one line.");
  2293.   put_help_line(" DN          Move forward one line.");
  2294.   put_help_line(" C-p         Move backward one line.");
  2295.   put_help_line(" UP          Move backward one line.");
  2296.   put_help_line(" C-v         Move forward one page.");
  2297.   put_help_line(" PGDN        Move forward one page.");
  2298.   put_help_line(" M-v         Move backward one page.");
  2299.   put_help_line(" PGUP        Move backward one page.");
  2300.   put_help_line(" M-<         Move to beginning of pane.");
  2301.   put_help_line(" HOME        Move to beginning of pane.");
  2302.   put_help_line(" M->         Move to end of pane.");
  2303.   put_help_line(" END         Move to end of pane.");
  2304.   put_help_line(" ");
  2305.   put_help_line("----------------------------------------------------------");
  2306.   put_help_line("DIALOG BOXES:");
  2307.   put_help_line(" ");
  2308.   put_help_line(" ESC ESC     Quit dialog box and discard any changes.");
  2309.   put_help_line(" C-g         Quit dialog box and discard any changes.");
  2310.   put_help_line(" TAB         Move to next field, if applicable.");
  2311.   put_help_line(" C-n         Move to next field, if applicable.");
  2312.   put_help_line(" DN          Move to next field, if applicable.");
  2313.   put_help_line(" S-TAB       Move to previous field, if applicable.");
  2314.   put_help_line(" C-p         Move to previous field, if applicable.");
  2315.   put_help_line(" UP          Move to previous field, if applicable.");
  2316.   put_help_line(" CR          Select highlighted item, if applicable.");
  2317.   put_help_line(" C-f         Move forward one character, if applicable.");
  2318.   put_help_line(" RT          Move forward one character, if applicable.");
  2319.   put_help_line(" C-b         Move backward one character, if applicable.");
  2320.   put_help_line(" LT          Move backward one character, if applicable.");
  2321.   put_help_line(" DEL         Delete character left of cursor.");
  2322.   put_help_line(" C-d         Delete character under cursor.");
  2323.   put_help_line(" CR          Accept input and");
  2324.   put_help_line("               - go to next field (if not on a button), or");
  2325.   put_help_line("               - take action specified by button.");
  2326.   put_help_line(" ");
  2327.   put_help_line("----------------------------------------------------------");
  2328.   put_help_line("MINBUFFER:");
  2329.   put_help_line(" ");
  2330.   put_help_line(" ESC ESC     Quit minibuffer and discard any changes.");
  2331.   put_help_line(" C-g         Quit minibuffer and discard any changes.");
  2332.   put_help_line(" C-f         Move forward one character, if applicable.");
  2333.   put_help_line(" RT          Move forward one character, if applicable.");
  2334.   put_help_line(" C-b         Move backward one character, if applicable.");
  2335.   put_help_line(" LT          Move backward one character, if applicable.");
  2336.   put_help_line(" DEL         Delete character left of cursor.");
  2337.   put_help_line(" C-d         Delete character under cursor.");
  2338.   put_help_line(" CR          Accept input.");
  2339.   put_help_line(" ");
  2340.   put_help_line("==========================================================");
  2341.   put_help_line(" PANE-SPECIFIC HELP");
  2342.   put_help_line("==========================================================");
  2343.   put_help_line("----------------------------------------------------------");
  2344.   put_help_line("HELP PANE:");
  2345.   put_help_line(" ");
  2346.   put_help_line(" CR          Make code pane active.");
  2347.   put_help_line(" C-g         Make code pane active.");
  2348.   put_help_line(" ");
  2349.   put_help_line("----------------------------------------------------------");
  2350.   put_help_line("CODE PANE:");
  2351.   put_help_line(" ");
  2352.   put_help_line(" s           Single step, stepping over function calls.");
  2353.   put_help_line(" S           Single step, stepping into function calls.");
  2354.   put_help_line(" C-c a       Animate - run program by single stepping at");
  2355.   put_help_line("             a user-specified speed.");
  2356.   put_help_line(" b           Toggle breakpoint on/off at current location.");
  2357.   put_help_line(" e           Edit breakpoint via dialog box.");
  2358.   put_help_line("             Breakpoint particulars are:");
  2359.   put_help_line("               Address   - breakpoint location.");
  2360.   put_help_line("               Type      - 0 == Code breakpoint.");
  2361.   put_help_line("                           1 == Data write breakpoint.");
  2362.   put_help_line("                           2 == Data read breakpoint.");
  2363.   put_help_line("               Class     - 0 == Always enabled.");
  2364.   put_help_line("                           1 == Breakpoint enabled only after");
  2365.   put_help_line("                                being reached <count> times.");
  2366.   put_help_line("                           2 == Breakpoint enabled only after");
  2367.   put_help_line("                                <condition> is true (nonzero).");
  2368.   put_help_line("               Count     - Number of hits before a class 1");
  2369.   put_help_line("                           breakpoint activates.");
  2370.   put_help_line("               Condition - Condition to be met before a");
  2371.   put_help_line("                           class 2 breakpoint activates.");
  2372.   put_help_line("                           The condition can be almost any");
  2373.   put_help_line("                           C expression.  For more info on");
  2374.   put_help_line("                           allowable expressions, see the");
  2375.   put_help_line("                           manual section on expressions.");
  2376.   put_help_line("                           Two examples are:");
  2377.   put_help_line(" _Odd_num >> 3 == 1 && (_Even_num >> _Shift_val || _Test)");
  2378.   put_help_line(" (([%esi + %eax * 4] & 0x5fff) >> 12) & 0x0f == 4");
  2379.   put_help_line("               Size      - The Size parameter allows you");
  2380.   put_help_line("                           to specify the maximum size to");
  2381.   put_help_line("                           be used during evaluation of");
  2382.   put_help_line("                           expressions.");
  2383.   put_help_line(" C-c t       Trace to current address.  Same as toggling");
  2384.   put_help_line("             breakpoint, then running program.");
  2385.   put_help_line(" <n> CR      Disassemble and display memory at specified");
  2386.   put_help_line("             decimal address.");
  2387.   put_help_line(" <x> CR      Disassemble and display memory at specified");
  2388.   put_help_line("             hexadecimal address.");
  2389.   put_help_line(" _<sym> CR   Disassemble and display memory at address");
  2390.   put_help_line("             specified by symbol <sym>.");
  2391.   put_help_line(" %<sym> CR   Disassemble and display memory at address");
  2392.   put_help_line("             specified by value in register denoted by");
  2393.   put_help_line("             symbol <sym>.");
  2394.   put_help_line(" <exp> CR    Disassemble and display memory at address");
  2395.   put_help_line("             specified by value of expression <exp>.");
  2396.   put_help_line(" i           Disassemble and display memory at address");
  2397.   put_help_line("             specified by EIP (current run location).");
  2398.   put_help_line(" C-c i       Set EIP to address of currently highlighted");
  2399.   put_help_line("             instruction.");
  2400.   put_help_line(" p           Modify performance analyzer settings.");
  2401.   put_help_line(" C-c p       Start performance analyzer and run program");
  2402.   put_help_line("             (if performance analyzer timer has been set).");
  2403.   put_help_line(" M-b         Move pane's origin left by one byte.");
  2404.   put_help_line(" M-f         Move pane's origin right by one byte.");
  2405.   put_help_line(" C-x / <c>   Save highlighted location in debugger code");
  2406.   put_help_line("             pane register <c>.");
  2407.   put_help_line(" C-x j <c>   Disassemble and display memory at location");
  2408.   put_help_line("             saved in debugger code pane register <c>.");
  2409.   put_help_line(" ");
  2410.   put_help_line("----------------------------------------------------------");
  2411.   put_help_line("DATA PANE:");
  2412.   put_help_line(" ");
  2413.   put_help_line(" w           Toggle data write breakpoint on/off.");
  2414.   put_help_line(" r           Toggle data read/write breakpoint on/off.");
  2415.   put_help_line(" e           Edit data read or read/write breakpoint.");
  2416.   put_help_line("             Breakpoint particulars are:");
  2417.   put_help_line("               Address   - breakpoint location.");
  2418.   put_help_line("               Type      - 0 == Code breakpoint.");
  2419.   put_help_line("                           1 == Data write breakpoint.");
  2420.   put_help_line("                           2 == Data read breakpoint.");
  2421.   put_help_line("               Class     - 0 == Always enabled.");
  2422.   put_help_line("                           1 == Breakpoint enabled only after");
  2423.   put_help_line("                                being reached <count> times.");
  2424.   put_help_line("                           2 == Breakpoint enabled only after");
  2425.   put_help_line("                                <condition> is true (nonzero).");
  2426.   put_help_line("               Count     - Number of hits before a class 1");
  2427.   put_help_line("                           breakpoint activates.");
  2428.   put_help_line("               Condition - Condition to be met before a");
  2429.   put_help_line("                           class 2 breakpoint activates.");
  2430.   put_help_line("                           The condition can be almost any");
  2431.   put_help_line("                           C expression.  For more info on");
  2432.   put_help_line("                           allowable expressions, see the");
  2433.   put_help_line("                           manual section on expressions.");
  2434.   put_help_line("                           Two examples are:");
  2435.   put_help_line(" _Odd_num >> 3 == 1 && (_Even_num >> _Shift_val || _Test)");
  2436.   put_help_line(" (([%esi + %eax * 4] & 0x5fff) >> 12) & 0x0f == 4");
  2437.   put_help_line("               Size      - The Size parameter allows you");
  2438.   put_help_line("                           to specify the maximum size to");
  2439.   put_help_line("                           be used during evaluation of");
  2440.   put_help_line("                           expressions.");
  2441.   put_help_line(" b           Display data in byte format.");
  2442.   put_help_line(" h           Display data in halfword (two byte) format.");
  2443.   put_help_line(" f           Display data in fullword (four byte) format.");
  2444.   put_help_line(" <n> CR      Display memory at specified decimal address.");
  2445.   put_help_line(" <x> CR      Display memory at specified hexadecimal");
  2446.   put_help_line("             address.");
  2447.   put_help_line(" _<sym> CR   Display memory at address specified by");
  2448.   put_help_line("             symbol <sym>.");
  2449.   put_help_line(" %<sym> CR   Display memory at address specified by value");
  2450.   put_help_line("             in register denoted by symbol <sym>.");
  2451.   put_help_line(" <exp> CR    Display memory at address specified by value");
  2452.   put_help_line("             of expression <exp>.");
  2453.   put_help_line(" i           Display memory at address specified by EIP");
  2454.   put_help_line("             (current run location).");
  2455.   put_help_line(" s           Display memory at address specified by ESP");
  2456.   put_help_line("             (current stack pointer).");
  2457.   put_help_line(" *           Dereference currently highlighted value.");
  2458.   put_help_line(" @           Retrace steps after a '*' command.  Up to");
  2459.   put_help_line("             five (5) steps back are allowed.");
  2460.   put_help_line(" n           Display data in customized format.");
  2461.   put_help_line(" p           Input/output from/to ports as follows:");
  2462.   put_help_line("               Size - 1 = byte, 2 = word, 3 = dword");
  2463.   put_help_line("                      b = byte, h = word, f = dword");
  2464.   put_help_line("               Port - port to access");
  2465.   put_help_line("               Data - data to write");
  2466.   put_help_line("               <In>  button - input from port");
  2467.   put_help_line("               <Out> button - output to port");
  2468.   put_help_line(" M-b         Move pane's origin left by one byte.");
  2469.   put_help_line(" M-f         Move pane's origin right by one byte.");
  2470.   put_help_line(" C-c m       Modify memory at cursor");
  2471.   put_help_line(" C-c u       Undo last memory modification.  No more than");
  2472.   put_help_line("             five (5) modifications can be undone.");
  2473.   put_help_line(" C-c s       Search memory.");
  2474.   put_help_line(" C-x / <c>   Save highlighted location in debugger data");
  2475.   put_help_line("             pane register <c>.");
  2476.   put_help_line(" C-x j <c>   Display memory at location saved in");
  2477.   put_help_line("             debugger data pane register <c>.");
  2478.   put_help_line(" ");
  2479.   put_help_line("----------------------------------------------------------");
  2480.   put_help_line("REGISTERS PANE:");
  2481.   put_help_line(" ");
  2482.   put_help_line(" C-c m       Modify register at cursor.");
  2483.   put_help_line(" C-c u       Undo last register modification.  No more");
  2484.   put_help_line("             than five (5) modifications can be undone.");
  2485.   put_help_line(" ");
  2486.   put_help_line("----------------------------------------------------------");
  2487.   put_help_line("FLAGS PANE:");
  2488.   put_help_line(" ");
  2489.   put_help_line(" All commands accessed via local menu.");
  2490.   put_help_line(" ");
  2491.   put_help_line("----------------------------------------------------------");
  2492.   put_help_line("BREAKPOINT PANE:");
  2493.   put_help_line(" ");
  2494.   put_help_line(" CR          Goto location of currently highlighted");
  2495.   put_help_line("             breakpoint, in code or data pane, as");
  2496.   put_help_line("             appropriate.");
  2497.   put_help_line(" DEL         Delete currently highlighted breakpoint.");
  2498.   put_help_line(" C-d         Delete currently highlighted breakpoint.");
  2499.   put_help_line(" C-e         Edit currently highlighted breakpoint.");
  2500.   put_help_line(" C-k         Delete from currently highlighted breakpoint");
  2501.   put_help_line("             up to the last breakpoint.");
  2502.   put_help_line(" C-y         Restore from previous deletion.  No more");
  2503.   put_help_line("             than five (5) deletions can be undone.");
  2504.   put_help_line(" ");
  2505.   put_help_line("----------------------------------------------------------");
  2506.   put_help_line("WHEREIS PANE:");
  2507.   put_help_line(" ");
  2508.   put_help_line(" CR          Display data/code at address represented by");
  2509.   put_help_line("             currently highlighted symbol.");
  2510.   put_help_line(" _<sym> CR   Find <sym> in symbol table");
  2511.   put_help_line("             Permissible wildcards are:");
  2512.   put_help_line("               ? - Matches one character");
  2513.   put_help_line("               * - Matches any number of characters");
  2514.   put_help_line(" ");
  2515.   put_help_line("----------------------------------------------------------");
  2516.   put_help_line("MODULE PANE:");
  2517.   put_help_line(" ");
  2518.   put_help_line(" CR          Prompt for a line number, disassemble and");
  2519.   put_help_line("             display code at that location.");
  2520.   put_help_line(" ");
  2521.   put_help_line("----------------------------------------------------------");
  2522.   put_help_line("NPX PANE: ");
  2523.   put_help_line(" ");
  2524.   put_help_line(" C-c e       Empty register.");
  2525.   put_help_line(" C-c n       Negate register contents.");
  2526.   put_help_line(" C-c z       Zero register.");
  2527.   put_help_line(" C-c m       Modify register contents.");
  2528.   put_help_line(" C-c u       Undo last register modification.  No more");
  2529.   put_help_line("             than five (5) modifications can be undone.");
  2530.   put_help_line(" ");
  2531.   put_help_line("----------------------------------------------------------");
  2532.   put_help_line("PERFORMANCE ANALYZER DATA VIEWER:");
  2533.   put_help_line(" ");
  2534.   put_help_line(" C-x C-w     Log performance analyzer results to file.");
  2535.   put_help_line(" ");
  2536.   put_help_line("----------------------------------------------------------");
  2537.   put_help_line("STACK PANE:");
  2538.   put_help_line(" ");
  2539.   put_help_line(" CR          Select highlighted location and display");
  2540.   put_help_line("             in data pane.");
  2541.   put_help_line(" ");
  2542.   put_help_line("----------------------------------------------------------");
  2543.   put_help_line("INFO PANE:");
  2544.   put_help_line(" ");
  2545.   put_help_line(" No commands available.");
  2546.   put_help_line(" ");
  2547.   put_help_line("==========================================================");
  2548.   put_help_line(" SYNTAX AND VALUES");
  2549.   put_help_line("==========================================================");
  2550.   put_help_line("----------------------------------------------------------");
  2551.   put_help_line("C EXPRESSIONS ALLOWED:");
  2552.   put_help_line(" ");
  2553.   put_help_line("   Syntax:");
  2554.   put_help_line("     <expr>  = <l_exp> [<l_op> <l_exp> ...]");
  2555.   put_help_line("     <l_exp> = <a_exp> [<r_op> <a_exp> ...] | ");
  2556.   put_help_line("               (<l_exp>) | !<l_exp>");
  2557.   put_help_line("     <a_exp> = <a_exp>|<identifier> [<a_op> ");
  2558.   put_help_line("               <a_exp>|<identifier> ...] | (<a_exp>)");
  2559.   put_help_line("     <identifier> = <identifier> | <[<a_exp>]><size>");
  2560.   put_help_line("   where");
  2561.   put_help_line("     <l_exp>      is a logical expression.");
  2562.   put_help_line("     <l_op>       is one of: && ||");
  2563.   put_help_line("     <a_exp>      is an arithmetic expression");
  2564.   put_help_line("     <r_op>       is one of: < <= == != >= >");
  2565.   put_help_line("     <a_op>       is one of: + - * / >> << & | ! ~");
  2566.   put_help_line("     <identifier> is an identifiler (a symbol, register) ");
  2567.   put_help_line("                  a number, or a memory reference.");
  2568.   put_help_line(" ");
  2569.   put_help_line("     * <identifier> can be a global variable name,");
  2570.   put_help_line("       symbolic constant, constant value, register name,");
  2571.   put_help_line("       or memory reference (i.e. an expression which");
  2572.   put_help_line("       evaluates to a memory location).");
  2573.   put_help_line("     * All register names must begin with a '%' (percent) ");
  2574.   put_help_line("       character. ");
  2575.   put_help_line("     * All memory references have the structure: ");
  2576.   put_help_line("         [<address expression>]size ");
  2577.   put_help_line("       where size can be b, h, f, or nothing.");
  2578.   put_help_line("       b: 1 byte. h: 2 bytes. f: 4 bytes. Any other");
  2579.   put_help_line("       character immediately following the right square ");
  2580.   put_help_line("       bracket (]) and is not one of the above characters");
  2581.   put_help_line("       will be interpreted as part of the expression.");
  2582.   put_help_line("       By default (if neither b, h, or f follows the");
  2583.   put_help_line("       right square bracket,) the reference will read");
  2584.   put_help_line("       4 bytes from memory.");
  2585.   put_help_line("     * When constructing expressions, be aware that");
  2586.   put_help_line("       the modulo (%) operator is not allowed, since");
  2587.   put_help_line("       it conficts with the register naming scheme.");
  2588.   put_help_line("       To perform a modulo, use divide (/) and");
  2589.   put_help_line("       subtract (-): (a % b) == (a - a / b)");
  2590.   put_help_line("     * When constructing expressions, be wary");
  2591.   put_help_line("       of possible overflow (the debugger uses");
  2592.   put_help_line("       32 bit arithmetic to evaluate expressions).");
  2593.   put_help_line(" ");
  2594.   put_help_line("   Examples of valid expressions: ");
  2595.   put_help_line(" ");
  2596.   put_help_line("     _Odd_num >> 3 == 1 && (_Even_num >> _Shift_val || _Test)");
  2597.   put_help_line("     (([%esi + %eax * 4] & 0x5fff) >> 12) & 0x0f == 4  ");
  2598.   put_help_line(" ");
  2599.   put_help_line("----------------------------------------------------------");
  2600.   put_help_line("REMOTE DEBUGGING DEVICES");
  2601.   put_help_line(" ");
  2602.   put_help_line("    con       : console. ");
  2603.   put_help_line("    com_one   : COM1. ");
  2604.   put_help_line("    com_two   : COM2. ");
  2605.   put_help_line("    com_three : COM3. ");
  2606.   put_help_line("    com_four  : COM4. ");
  2607.   put_help_line(" ");
  2608.   put_help_line("==========================================================");
  2609. }
  2610. /* ---------------------------------------------------------------------- */
  2611. static void
  2612. initialize (void)
  2613. { int i;
  2614.  
  2615.   using_com_port_num = remote;
  2616.   init_io (using_com_port_num);
  2617.   if (_go32_info_block.run_mode != _GO32_RUN_MODE_DPMI)
  2618.     test_npx ();
  2619.  
  2620.   debug_screen_p = 0;
  2621.   toplines = (rows / 2) + 4;
  2622.   bottomlines = rows - 4 - toplines;
  2623.   main_x1 = cols - 18;
  2624.   main_x2 = cols - 5;
  2625.   main_x3 = 46;                  
  2626.  
  2627.   code_pane_pos = malloc ((rows + 2) * sizeof (word32));
  2628.   stack_dump_pos = malloc ((rows + 2) * sizeof (word32));
  2629.  
  2630.   debug_screen_save = get_screen ();
  2631.   debug_screen_save[1] = debug_screen_save[2] = 0;  /* Patch cursor pos.  */
  2632.  
  2633.   pane = 10;
  2634.   pane_pos = 0;
  2635.   for (i = 0; i < PANECOUNT; i++) pane_positions[i] = 0;
  2636.   data_dump_origin = areas[A_data].first_addr;
  2637.   data_dump_size = 1;
  2638.   code_dump_origin = a_tss.tss_eip;
  2639.   stack_dump_origin = 0;
  2640.   breakpoint_origin = 0;
  2641.   breakpoint_count = 0;
  2642.   breakpoint_table = malloc (breakpoint_count * sizeof (BP_ENTRY));
  2643.   whereis_origin = 0;
  2644.   whereis_sym_count = 0;
  2645.   whereis_pane_sym = malloc (whereis_sym_count * sizeof (char *));
  2646.   module_origin = 0;
  2647.   module_text_count = 0;
  2648.   module_pane_text = malloc (module_text_count * sizeof (char *));
  2649.   init_module ();
  2650.   help_origin = 0;
  2651.   help_text_count = 0;
  2652.   help_pane_text = malloc (help_text_count * sizeof (char *));
  2653.   init_help();
  2654.   flag_pane_origin = 0;
  2655.   reg_pane_origin = 0;
  2656.   help_pane_active = 1;
  2657.   npx_pane_active = stack_pane_active = info_pane_active
  2658.     = whereis_pane_active = module_pane_active
  2659.     = code_pane_active = 0;
  2660.   sprintf (active_pane_name, "Help Pane");
  2661.   
  2662.   init_eval_data (0, 0); /* Force to calculate addresses */
  2663.   init_undo (&data_undo, free_do_nothing);
  2664.   init_undo (®ister_undo, free_do_nothing);
  2665.   init_undo (&npx_undo, free_npx);
  2666.   init_undo (&breakpoint_undo, free_breakpoint);                          
  2667.  
  2668.   redraw (1);
  2669.   message (CL_Info, "Ladybug version %d.%02d", MAJOR_VER, MINOR_VER);
  2670. }
  2671. /* ---------------------------------------------------------------------- */
  2672. static void
  2673. view_eval_data (void)
  2674. {
  2675.   EVAL_SEG_INFO swap_data;
  2676.   EVAL_DATA_TABLE temp_data;
  2677.   int i, j, percent_bar;
  2678.   long percent;
  2679.   int32 delta;
  2680.   word32 total_hits = 0, in_hits = 0, out_hits;
  2681.   char *save, *name = alloca (256), *name2 = alloca (256), *p;
  2682.  
  2683.   if (total_hits_count == 0)
  2684.   { message (CL_Error,
  2685.              "Nothing has been recorded, cannot calculate percentage");
  2686.     return;
  2687.   }
  2688.  
  2689.   for (i = 0; i < EVAL_SEGMENTS; i++)
  2690.   { temp_data[i].start_addr = evaluation_data[i].start_addr;
  2691.     temp_data[i].stop_addr  = evaluation_data[i].stop_addr;
  2692.     temp_data[i].hits_count = evaluation_data[i].hits_count;
  2693.     total_hits += temp_data[i].hits_count;
  2694.   }
  2695.  
  2696.   for (i = 0; i < EVAL_SEGMENTS - 1; i++)
  2697.     for (j = i + 1; j < EVAL_SEGMENTS; j++)
  2698.       if (temp_data[i].hits_count < temp_data[j].hits_count)
  2699.       {    swap_data.start_addr = temp_data[i].start_addr;
  2700.         swap_data.stop_addr  = temp_data[i].stop_addr;
  2701.         swap_data.hits_count = temp_data[i].hits_count;
  2702.  
  2703.         temp_data[i].start_addr = temp_data[j].start_addr;
  2704.         temp_data[i].stop_addr  = temp_data[j].stop_addr;
  2705.         temp_data[i].hits_count = temp_data[j].hits_count;
  2706.  
  2707.         temp_data[j].start_addr = swap_data.start_addr;
  2708.         temp_data[j].stop_addr  = swap_data.stop_addr;
  2709.         temp_data[j].hits_count = swap_data.hits_count;
  2710.       }
  2711.   j = (rows / 2) - 4;
  2712.   save = debug_screen_save;
  2713.   debug_screen_save = get_screen ();
  2714.   screen_attr = screen_attr_normal;
  2715.   clear_screen ();
  2716.   screen_attr = screen_attr_ffocus;
  2717.   double_frame (0, 0, cols - 1, rows - 1, "Performance Analyzer's Result");
  2718.   screen_attr = screen_attr_normal;
  2719.  
  2720.   sprintf (name, "Most called segments (from %08lx to %08lx)",
  2721.            evaluation_data[0].start_addr, 
  2722.            evaluation_data[EVAL_SEGMENTS - 1].stop_addr);
  2723.   putl (cols / 2 - 24, 1, 50, name);
  2724.   for (i = 0; i < j; i++)
  2725.     in_hits += temp_data[i].hits_count;
  2726.  
  2727.   if (in_hits == 0)
  2728.     putl (2, 3, cols-5, "Nothing is recorded inside the given addresses.");
  2729.   else
  2730.   { for (i = 0; i < j; i++)
  2731.     {                                                                           
  2732.       percent = (long)temp_data[i].hits_count;
  2733.       percent *= 100;
  2734.  
  2735.       p = syms_val2name (temp_data[i].start_addr, &delta);
  2736.       if (p[0] != '0')
  2737.         if (delta)
  2738.           sprintf (name, "(%s+%#lx)", p, delta);
  2739.         else
  2740.           sprintf (name, "(%s)",p);
  2741.       else
  2742.         sprintf(name, "(No Symbols");
  2743.       p = syms_val2name (temp_data[i].stop_addr, &delta);
  2744.       if (p[0] != '0')
  2745.         if (delta)
  2746.           sprintf (name2, "(%s+%#lx)", p, delta);
  2747.         else
  2748.           sprintf (name2, "(%s)", p);
  2749.       else
  2750.         sprintf(name2, "No Symbols)");
  2751.  
  2752.       sprintf (read_buffer, "%02ld.%-1ld%% %08lx-%08lx %s-%s",
  2753.                percent / total_hits, ((percent % total_hits) * 10) / total_hits,
  2754.                temp_data[i].start_addr, temp_data[i].stop_addr,
  2755.                name, name2);
  2756.       percent /= 100;
  2757.       percent_bar = percent * (cols - 5) / total_hits;
  2758.  
  2759.       putl (2, i * 2 + 3, cols - 4, read_buffer);
  2760.       draw (2, i * 2 + 4, '-', 1, percent_bar);
  2761.     }
  2762.  
  2763.     out_hits = total_hits - in_hits;
  2764.     percent = out_hits * 100;
  2765.  
  2766.     sprintf (name, "%02ld.%-1ld%% : Other segments (%% of total in-range hits)", 
  2767.              percent / total_hits, ((percent % total_hits) * 10) / total_hits);
  2768.     putl (2, i * 2 + 3, cols - 4, name);           
  2769.     percent /= 100;
  2770.     percent_bar = percent * (cols - 5) / in_hits;
  2771.     draw (2, i * 2 + 4, '-', 1, percent_bar);
  2772.     i++;
  2773.   }
  2774.   out_hits = total_hits_count - total_hits;
  2775.   percent = out_hits * 100;
  2776.  
  2777.   sprintf (name, "%02ld.%-1ld%% : Outside of defined range (over total of %010ld)",
  2778.            percent / total_hits_count, 
  2779.            ((percent % total_hits_count) * 10) / total_hits_count, 
  2780.            total_hits_count);
  2781.   putl (2, i * 2 + 3, cols - 4, name);               
  2782.   percent /= 100;
  2783.   percent_bar = percent * (cols - 5) / total_hits_count;
  2784.   draw (2, i * 2 + 4, '-', 1, percent_bar);
  2785.  
  2786.   put_screen (debug_screen_save);
  2787.   do
  2788.   { i = getykey ();
  2789.     if (i == K_Control_X)
  2790.     { i = getykey ();
  2791.       if (i == K_Control_W)
  2792.       { write_log (1, 1, cols - 1, rows - 1);
  2793.         i = 0;
  2794.       }
  2795.     }
  2796.   } while (i == 0);
  2797.   free (debug_screen_save);
  2798.   debug_screen_save = save;
  2799.   put_screen (debug_screen_save);
  2800. }
  2801. /* ---------------------------------------------------------------------- */
  2802. static void
  2803. init_time (char *output, char *input, word32 addr)
  2804. { sprintf (output, "%s", *(int *)addr ? "On " : "Off");
  2805. }
  2806. /* ---------------------------------------------------------------------- */
  2807. static int
  2808. edtime (char *text, word32 addr, int x, int y, int len, int *key)
  2809. { if (*key == K_Return)                       /* Only enter toggles timer */
  2810.   { if (*(int *)addr)
  2811.       reset_timer ();
  2812.     else
  2813.       set_timer ();
  2814.   }
  2815.   *key = 0;
  2816.   return 1;
  2817. }          
  2818. /* ---------------------------------------------------------------------- */
  2819. static int
  2820. action_init (DIALOG_ITEM dialog_data[])
  2821. { word32 start_addr = 0, stop_addr = 0;
  2822.   int ok;
  2823.  
  2824.   if (!my_read_string ("Enter start address: "))
  2825.     start_addr = parse_expression(4, read_buffer, &ok); 
  2826.   if (ok != ParseError_ok)
  2827.   { message (CL_Error, "Bad address: %s", read_buffer);
  2828.     return (0);
  2829.   }
  2830.   if (!my_read_string ("Enter stop address: "))
  2831.     stop_addr = parse_expression(4, read_buffer, &ok);
  2832.   if (ok != ParseError_ok)
  2833.   { message (CL_Error, "Bad address: %s", read_buffer);
  2834.     return (0);
  2835.   }
  2836.   init_eval_data (start_addr, stop_addr);
  2837.   return (1);
  2838. }
  2839. /* ---------------------------------------------------------------------- */
  2840. static int
  2841. action_view (DIALOG_ITEM dialog_data[])
  2842. { view_eval_data ();
  2843.   return (1);
  2844. }
  2845. /* ---------------------------------------------------------------------- */
  2846. static void
  2847. evaluation_dialogue (void)
  2848. { int ret = 0;
  2849.   static DIALOG_ITEM dialog_data[] = {
  2850.     {"Timer    :", 0 , 03, 1, format_asis, eval_asis, init_time, edtime},
  2851.     {"Segments :", 0 , 05, 0, format_int , eval_word, init_int , editor},
  2852.     {0           , 0 , 0 , 0, 0          , 0        , 0        , 0     }
  2853.   };
  2854.   static BUTTON_ITEM button_data[] = {
  2855.     {" ReInit ", 1, action_init},
  2856.     {"  View  ", 1, action_view},
  2857.     {"  Done  ", 0, action_done},
  2858.     {0         , 0, 0          }
  2859.   };
  2860.   dialog_data[0].return_addr = (word32)&timer_is_set;
  2861.   dialog_data[1].return_addr = (word32)&total_segments;
  2862.   dialog ("P.A. Settings", dialog_data, button_data, &ret);
  2863. }
  2864. /* ---------------------------------------------------------------------- */
  2865. static MENU_ITEM Code_Local_Menu[] = {
  2866.        {"Current Highlighted Item               ", 1        , ""     , 0},
  2867.        {"Run                                ~^R~", ITEM_TYPE, "\022" , 0},
  2868.        {"Step into function                  ~S~", ITEM_TYPE, "S"    , 0},
  2869.        {"Step over function                  ~s~", ITEM_TYPE, "s"    , 0},
  2870.        {"Trace to current address         ~^C t~", ITEM_TYPE, "\3t"  , 0},
  2871.        {"Animate                          ~^C a~", ITEM_TYPE, "\3a"  , 0},
  2872.        {"Toggle breakpoint                   ~b~", ITEM_TYPE, "b"    , 0},
  2873.        {"Toggle/edit breakpoint              ~e~", ITEM_TYPE, "e"    , 0},
  2874.        {"Perfomance analyzer settings        ~p~", ITEM_TYPE, "p"    , 0},
  2875.        {"Start performance analyzer       ~^C p~", ITEM_TYPE, "\3p"  , 0},
  2876.        {"Display code at EIP                 ~i~", ITEM_TYPE, "i"    , 0},
  2877.        {"Set EIP to current address       ~^C i~", ITEM_TYPE, "\3i"  , 0},
  2878.        {"Move pane's origin left one byte  ~M b~", ITEM_TYPE, "\033b", 0},
  2879.        {"Move pane's origin right one byte ~M f~", ITEM_TYPE, "\033f", 0},
  2880.        {0                                        , 0        , ""     , 0}
  2881. };                                                     
  2882. /* ---------------------------------------------------------------------- */
  2883. static void
  2884. code_pane_command (int key)
  2885. { int b;
  2886.             
  2887.   if (key == 0)
  2888.   { pop_menu (Code_Local_Menu, "Code", 1, 3, &b);
  2889.     control_c = 0;
  2890.     control_x = 0;
  2891.     escaped   = 0;
  2892.     switch (b)
  2893.     { case 1:
  2894.         step (2);    /* Run is a global command... */
  2895.         break;
  2896.       case 2:  
  2897.         key = 'S';
  2898.         break;
  2899.       case 3:    
  2900.         key = 's';
  2901.         break;
  2902.       case 4:  
  2903.         control_c = 1;
  2904.         key = 't';
  2905.         break;                                         
  2906.       case 5:
  2907.         control_c = 1;
  2908.         key = 'a';
  2909.         break;
  2910.       case 6:
  2911.         key = 'b';
  2912.         break;
  2913.       case 7:
  2914.         key = 'e';
  2915.         break;
  2916.       case 8:
  2917.         key = 'p';
  2918.         break;
  2919.       case 9:    
  2920.         control_c = 1;
  2921.         key = 'p';
  2922.         break;
  2923.       case 10:
  2924.         key = 'i';
  2925.         break;
  2926.       case 11:   
  2927.         control_c = 1;
  2928.         key = 'i';
  2929.         break;
  2930.       case 12:
  2931.         escaped = 1;
  2932.         key = 'b';
  2933.         break;
  2934.       case 13:
  2935.         escaped = 1;
  2936.         key = 'f';
  2937.         break;
  2938.     }  
  2939.   }
  2940.   if (control_c)
  2941.   { switch (key)
  2942.     { case 'a':                            /* Animate               */
  2943.         if (using_com_port_num)
  2944.         { message (CL_Error, "Local mode only.");
  2945.           break;
  2946.         }
  2947.         if (!my_read_string("Time between step (tens of msecs): "))
  2948.         { unsigned long milisec;
  2949.           char *endp;
  2950.           int stopped = 0;
  2951.  
  2952.           milisec = strtoul(read_buffer, &endp, 10);
  2953.           if (milisec > 0)
  2954.             while (!stopped)
  2955.             { step(0);
  2956.              stopped = short_sleep(milisec);
  2957.             }
  2958.         }
  2959.         break;
  2960.       case 't':                            /* Trace                 */
  2961.         b = set_breakpoint (BP_Code, 0, code_pane_pos[pane_pos]);
  2962.         step (2);
  2963.         reset_breakpoint (b);
  2964.         break;
  2965.       case 'i':                            /* Set EIP to current    */
  2966.         a_tss.tss_eip = code_pane_pos[pane_pos];
  2967.         break;
  2968.       case 'p':                            /* Start perfom. analyzer*/
  2969.         if (timer_is_set)
  2970.         { start_evaluate ();
  2971.           step (2);
  2972.           stop_evaluate ();
  2973.           reset_timer ();
  2974.         } else
  2975.           message (CL_Error, "Timer has not been set -- Action aborted.");
  2976.         break;
  2977.     }
  2978.   }
  2979.   if (control_x)
  2980.   { switch (key)
  2981.     { case '/':                            /* Save to register      */
  2982.         key = my_get_char ("Save address to which register (0..A..z)? ");
  2983.         if (key >= '0' && key <= 'z')
  2984.            registers[key - '0'] = code_pane_pos[pane_pos];
  2985.         break;
  2986.       case 'j':                            /* Load from register    */
  2987.       case 'J':       
  2988.         key = my_get_char ("Load address from which register (0..A..z)? ");
  2989.         if (key >= '0' && key <= 'z')
  2990.           if (registers[key - '0'])
  2991.             code_pane_goto (registers[key - '0']);
  2992.         break;
  2993.     }                                                           
  2994.   }
  2995.   if (escaped)
  2996.   { switch (key)
  2997.     { case 'b':                            /* Move origin left      */
  2998.       case 'B':       
  2999.         code_dump_origin--;
  3000.         break;
  3001.       case 'f':                            /* Move origin right     */
  3002.       case 'F':       
  3003.         code_dump_origin++;
  3004.         break;
  3005.       case 'v':                            /* PageUp                */
  3006.       case 'V':       
  3007.         escaped = 0;
  3008.         key = K_PageUp;
  3009.         break;
  3010.     }                                                           
  3011.   }
  3012.   if (!(control_c || control_x || escaped))
  3013.   { switch (key)
  3014.     { case K_Up:
  3015.       case K_EUp:
  3016.       case K_Control_B:
  3017.       case K_Control_P:
  3018.         if (pane_pos > 0)
  3019.           pane_pos--;
  3020.         else
  3021.           code_pane_goto (code_skip (code_dump_origin, -1));
  3022.         break;
  3023.       case K_Down:
  3024.       case K_EDown:    
  3025.       case K_Control_F:
  3026.       case K_Control_N:
  3027.         if (pane_pos < toplines - 2)
  3028.           pane_pos++;
  3029.         else
  3030.           code_dump_origin =
  3031.              code_pane_pos[0] == code_pane_pos[1]
  3032.              ? code_pane_pos[2] : code_pane_pos[1];
  3033.         break;
  3034.       case K_PageUp:
  3035.       case K_EPageUp:  
  3036.         code_dump_origin = code_skip (code_dump_origin, 2 - toplines);
  3037.         break;
  3038.       case K_PageDown:
  3039.       case K_EPageDown:
  3040.       case K_Control_V:
  3041.         code_dump_origin = code_dump_last + 1;
  3042.         break;
  3043.       case 'b':
  3044.       case 'B':
  3045.         b = get_breakpoint (BP_Code, -1, code_pane_pos[pane_pos]);
  3046.         if (b != -1)
  3047.           reset_breakpoint (b);
  3048.         else
  3049.           b = set_breakpoint (BP_Code, 4, code_pane_pos[pane_pos]);
  3050.         break;
  3051.       case 'e':
  3052.       case 'E':
  3053.         b = get_breakpoint (BP_Code, -1, code_pane_pos[pane_pos]);
  3054.         if (b == -1)
  3055.         { b = set_breakpoint (BP_Code, 4, code_pane_pos[pane_pos]);
  3056.           if (edit_breakpoint(b))
  3057.             reset_breakpoint (b);
  3058.         } else
  3059.           edit_breakpoint (b);
  3060.         break;
  3061.       case 'i':
  3062.       case 'I':
  3063.         code_pane_goto (a_tss.tss_eip);
  3064.         break;
  3065.       case 'p':
  3066.       case 'P':
  3067.         evaluation_dialogue ();
  3068.         break;
  3069.       case 's':
  3070.         step (1);
  3071.         break;
  3072.       case 'S':
  3073.         step (0);
  3074.         break;
  3075.       default:
  3076.         if ((key == '_') || (key == '%') ||
  3077.             (key == '(') || (key >= '0' && key <= '9'))
  3078.         { int res, ok;
  3079.           char s[2], *p;
  3080.     
  3081.           s[0] = key; s[1] = '\0';
  3082.           if (last_addr[0])
  3083.             ok = !read_string (last_addr);
  3084.           else
  3085.             ok = !read_string (key == '=' ? "" : s);
  3086.           strcpy (last_addr, read_buffer);
  3087.           p = read_buffer;
  3088.           while (*p != 0 && *p == ' ')
  3089.             p++;
  3090.           if (*p)
  3091.           { if (ok)
  3092.             { res = parse_expression (4, read_buffer, &ok);
  3093.               if (ok == ParseError_ok) 
  3094.               { message (CL_Info, "Found address %s.", read_buffer);
  3095.                 code_pane_goto (res);
  3096.                 last_addr[0] = 0;
  3097.               }
  3098.               else
  3099.                 message (CL_Error, "Bad address: %s", read_buffer);
  3100.             }
  3101.           }
  3102.         }
  3103.         break;
  3104.     }
  3105.   }
  3106.   redraw (0);
  3107. }
  3108. /* ---------------------------------------------------------------------- */
  3109. static MENU_ITEM Register_Local_Menu[] = {
  3110.        {"Current Highlighted Item      ", 1        , ""   , 0},
  3111.        {"Modify current register ~^C m~", ITEM_TYPE, "\3m", 0},
  3112.        {"Undo last modification  ~^C u~", ITEM_TYPE, "\3u", 0},
  3113.        {0                               , 0        , ""   , 0}
  3114. };                                                     
  3115. /* ---------------------------------------------------------------------- */
  3116. static void
  3117. register_pane_command (int key)
  3118. { int curr = pane_pos + reg_pane_origin;
  3119.   int b;
  3120.  
  3121.   if (key == 0)
  3122.   { pop_menu (Register_Local_Menu, "Registers", cols - 33, 3, &b);
  3123.     switch (b)
  3124.     { case 1: 
  3125.         control_c = 1;
  3126.         key = 'm';
  3127.         break;
  3128.       case 2:
  3129.         control_c = 1;
  3130.         key = 'u';
  3131.         break;
  3132.     }
  3133.   }               
  3134.   if (control_c)
  3135.   { switch (key)
  3136.     { case 'm':
  3137.       case 'M':
  3138.       { int res, ok;
  3139.         if (!my_read_string ("New value: ") && read_buffer[0])
  3140.         { res = parse_expression (4, read_buffer, &ok);
  3141.           if (ok == ParseError_ok)
  3142.             switch (regs_type[curr])
  3143.             { case 's':
  3144.                 put_undo (®ister_undo, (word32)(regs_addr[curr]),
  3145.                           *regs_addr[curr], 2);
  3146.                 *(unsigned short *)(regs_addr[curr]) = res & 0xffff;
  3147.                 break;
  3148.               case 'f':
  3149.                 put_undo (®ister_undo, 0,
  3150.                           a_tss.tss_eflags, 0);
  3151.                 a_tss.tss_eflags = (a_tss.tss_eflags & ~0xed5) | (res & 0xed5);
  3152.                 break;
  3153.               default:
  3154.                 put_undo (®ister_undo, (word32)(regs_addr[curr]),
  3155.                           *regs_addr[curr], 4);
  3156.                 *regs_addr[curr] = res;
  3157.             }
  3158.           else message (CL_Error, "Bad expression: %s", read_buffer);
  3159.         }
  3160.         break;
  3161.       }        
  3162.       case 'u':
  3163.       case 'U':                                  
  3164.       { word32 u_addr, u_val;
  3165.         int u_size;
  3166.  
  3167.         if (get_undo (®ister_undo, &u_addr, &u_val, &u_size))
  3168.         { switch (u_size)
  3169.           { case 2:      /* 's' */
  3170.               *(unsigned short *)(u_addr) = u_val & 0xffff;
  3171.               break;
  3172.             case 0:      /* 'f' */
  3173.               a_tss.tss_eflags = (a_tss.tss_eflags & ~0xed5) | (u_val & 0xed5);
  3174.               break;
  3175.             case 4:
  3176.               *(word32 *)u_addr = u_val;
  3177.               break;
  3178.           }
  3179.         }
  3180.         break;     
  3181.       }
  3182.     }
  3183.   }
  3184.   if (!(escaped || control_c || control_x))
  3185.     switch (key)
  3186.     { case K_Left:
  3187.       case K_ELeft:
  3188.       case K_Up:
  3189.       case K_EUp:
  3190.       case K_Control_P:
  3191.       case K_Control_B:
  3192.         if (pane_pos > 0)
  3193.           pane_pos--;
  3194.         else if (reg_pane_origin)
  3195.           reg_pane_origin--;
  3196.         break;
  3197.       case K_Right:
  3198.       case K_ERight:
  3199.       case K_Down:
  3200.       case K_EDown:
  3201.       case K_Control_N:
  3202.       case K_Control_F:
  3203.         if (regs_type[pane_pos + reg_pane_origin + 1])
  3204.           if (pane_pos < toplines - 2)
  3205.             pane_pos++;
  3206.           else
  3207.             reg_pane_origin++;
  3208.         break;
  3209.     }
  3210.   redraw (0);
  3211. }
  3212. /* ---------------------------------------------------------------------- */
  3213. static MENU_ITEM Flag_Local_Menu[] = {
  3214.        {"Current      ", 1        , "" , 0},
  3215.        {"~T~oggle flag", ITEM_TYPE, "t", 0},
  3216.        {"~S~et flag   ", ITEM_TYPE, "s", 0},
  3217.        {"~R~eset flag ", ITEM_TYPE, "r", 0},
  3218.        {0              , 0        , "" , 0}
  3219. };                                                     
  3220. /* ---------------------------------------------------------------------- */
  3221. static void
  3222. flag_pane_command (int key)
  3223. { static unsigned flagbits[] =
  3224.     { 0x0001, 0x0004, 0x0010, 0x0040, 0x0080, 0x0200, 0x0400, 0x0800 };
  3225.   int b, curr = pane_pos + flag_pane_origin;
  3226.  
  3227.   if (key == 0)
  3228.   { pop_menu (Flag_Local_Menu, "Flag", cols - 20, 3, &b);
  3229.     switch (b)
  3230.     { case 1:  
  3231.         a_tss.tss_eflags ^= flagbits[curr];
  3232.         break;
  3233.       case 2:
  3234.         a_tss.tss_eflags |= flagbits[curr];
  3235.         break;
  3236.       case 3:
  3237.         a_tss.tss_eflags &= ~flagbits[curr];
  3238.         break;
  3239.     }  
  3240.   }
  3241.   if (!(escaped || control_c || control_x))
  3242.     switch (key)
  3243.     { case K_Left:
  3244.       case K_ELeft:
  3245.       case K_Up:
  3246.       case K_EUp:
  3247.       case K_Control_P:
  3248.       case K_Control_B:
  3249.         if (pane_pos > 0)
  3250.           pane_pos--;
  3251.         else if (flag_pane_origin)
  3252.           flag_pane_origin--;
  3253.         break;
  3254.       case K_Right:
  3255.       case K_ERight:
  3256.       case K_Down:
  3257.       case K_EDown:
  3258.       case K_Control_N:
  3259.       case K_Control_F:
  3260.         if (curr < 7)
  3261.           if (pane_pos < toplines - 2)
  3262.             pane_pos++;
  3263.           else
  3264.             flag_pane_origin++;
  3265.         break;
  3266.     }
  3267.   redraw (0);
  3268. }
  3269. /* ---------------------------------------------------------------------- */
  3270. static MENU_ITEM Breakpoint_Local_Menu[] = {
  3271.        {"Current Highlighted Item          ", 1        , ""    , 0},
  3272.        {"Delete breakpoint             ~^D~", ITEM_TYPE, "\4"  , 0},
  3273.        {"Edit breakpoint               ~^E~", ITEM_TYPE, "\5"  , 0},
  3274.        {"Display Breakpoint                ", ITEM_TYPE, ""    , 0},
  3275.        {"Clear from current breakpoint ~^K~", ITEM_TYPE, "\013", 0},
  3276.        {"Restore breakpoint(s)         ~^Y~", ITEM_TYPE, "\031", 0},
  3277.        {0                                   , 0        , ""    , 0}
  3278. };                                                     
  3279. /* ---------------------------------------------------------------------- */
  3280. static void
  3281. breakpoint_pane_command (int key)
  3282. {
  3283.   int b = breakpoint_count ? pane_pos + breakpoint_origin : -1;
  3284.   int last = breakpoint_count && (b == breakpoint_count - 1);
  3285.   BP_ENTRY *del_bp;
  3286.  
  3287.   if (key == 0)
  3288.   { pop_menu (Breakpoint_Local_Menu, "Breakpoint", cols - 40, rows - 15, &b);
  3289.     control_c = 0;
  3290.     control_x = 0;
  3291.     escaped   = 0;
  3292.     switch (b)
  3293.     { case 1:
  3294.         key = K_Control_D;
  3295.         break;
  3296.       case 2:             
  3297.         key = K_Control_E;
  3298.         break;
  3299.       case 3:             
  3300.         key = K_Return;
  3301.         break;
  3302.       case 4:  
  3303.         key = K_Control_K;
  3304.         break;         
  3305.       case 5:
  3306.         key = K_Control_Y;
  3307.         break;
  3308.     }  
  3309.   }
  3310.   b = breakpoint_count ? pane_pos + breakpoint_origin : -1;
  3311.   if (!(escaped || control_c || control_x))
  3312.     switch (key)
  3313.     { case K_Delete:
  3314.       case K_EDelete:
  3315.       case K_Control_D:
  3316.         if (b != -1)
  3317.           reset_breakpoint (b);
  3318.         if (!last)
  3319.           break;
  3320.         /* else fall through */
  3321.       case K_Left:
  3322.       case K_ELeft:
  3323.       case K_Up:
  3324.       case K_EUp:
  3325.       case K_Control_P:
  3326.       case K_Control_B:
  3327.         if (pane_pos > 0)
  3328.           pane_pos--;
  3329.         else
  3330.           if (breakpoint_origin > 0)
  3331.         breakpoint_origin--;
  3332.         break;
  3333.       case K_Right:
  3334.       case K_ERight:
  3335.       case K_Down:
  3336.       case K_EDown:
  3337.       case K_Control_N:
  3338.       case K_Control_F:
  3339.         if (!last)
  3340.           if (pane_pos < bottomlines / 2 - 1)
  3341.           pane_pos++;
  3342.         else
  3343.           breakpoint_origin++;
  3344.         break;
  3345.       case K_Return:
  3346.         if (b != -1)
  3347.           if (breakpoint_table[b].type == BP_Code)
  3348.           code_pane_goto (breakpoint_table[b].addr);
  3349.           else
  3350.             data_dump_origin = breakpoint_table[b].addr;
  3351.         break;
  3352.       case K_Control_E:
  3353.         if (b != -1)
  3354.           edit_breakpoint(b);
  3355.         break;
  3356.       case K_Control_K:
  3357.       { int temp = breakpoint_count - 1;
  3358.         if (b >= 0)
  3359.           while (temp >= b)
  3360.             reset_breakpoint (temp--);
  3361.         break;
  3362.       }       
  3363.       case K_Control_Y:
  3364.       { word32 u_addr, u_val;
  3365.         int u_size;
  3366.  
  3367.         if (get_undo (&breakpoint_undo, &u_addr, &u_val, &u_size))
  3368.         { del_bp = (BP_ENTRY *)u_val;
  3369.           b = set_breakpoint (del_bp->type, del_bp->length, del_bp->addr);
  3370.           breakpoint_table[b].sub_type = del_bp->sub_type;
  3371.           breakpoint_table[b].count    = del_bp->count;
  3372.           strcpy (breakpoint_table[b].condition, del_bp->condition);
  3373.           free (del_bp);
  3374.         }
  3375.         break;
  3376.       }     
  3377.     }
  3378.   redraw (0);
  3379. }
  3380. /* ---------------------------------------------------------------------- */
  3381. static int
  3382. action_search (DIALOG_ITEM dialog_data[])
  3383. { int size          = *(int *)(dialog_data[0].return_addr);
  3384.   word32 start_at   = *(word32 *)(dialog_data[1].return_addr);
  3385.   word32 search_for = *(word32 *)(dialog_data[2].return_addr);
  3386.   word8  search_byte, *mem_byte;
  3387.   word16 search_word, *mem_word;
  3388.   word32 stop_at,     *mem_long;
  3389.   int i, buf_size, found = 0;
  3390.  
  3391.   stop_at = start_at;
  3392.   if (!size || !valid_addr (start_at, size))
  3393.     return (0);
  3394.   for (i = 0; i < MAX_AREA && !found; i++)
  3395.     if (start_at + size <= areas[i].last_addr &&
  3396.         start_at >= areas[i].first_addr)
  3397.     { stop_at = areas[i].last_addr;
  3398.       found = 1;
  3399.     }
  3400.   if (!found && start_at + size <= dos_mem_hi && start_at >= dos_mem_lo)
  3401.   { stop_at = dos_mem_hi;
  3402.     found = 1;
  3403.   }
  3404.   if (!found)
  3405.     return (0);
  3406.   found = 0;
  3407.   switch (size)
  3408.   { case 1:
  3409.       search_byte = (word8)(search_for & 0xff);
  3410.       do
  3411.       { if (stop_at < start_at + size)
  3412.           break;
  3413.         buf_size = stop_at - start_at;
  3414.         if (buf_size > 4096)
  3415.           buf_size = 4096;
  3416.         read_child (start_at, read_buffer, buf_size);
  3417.         mem_byte = (word8 *)read_buffer;
  3418.         for (i = 0; i < buf_size; i++)
  3419.           if (mem_byte[i] == search_byte)
  3420.           { found = 1;
  3421.             start_at += i;
  3422.             break;
  3423.           }
  3424.         if (!found)
  3425.           start_at += 4096;
  3426.       } while (!found);
  3427.       break;
  3428.     case 2:
  3429.       search_word = (word16)(search_for & 0xffff);
  3430.       do
  3431.       { if (stop_at < start_at + size)
  3432.           break;
  3433.         buf_size = stop_at - start_at;
  3434.         if (buf_size > 4096)
  3435.           buf_size = 4096;
  3436.         read_child (start_at, read_buffer, buf_size);
  3437.         buf_size /= 2;
  3438.         mem_word = (word16 *)read_buffer;
  3439.         for (i = 0; i < buf_size; i++)
  3440.           if (mem_word[i] == search_word)
  3441.           { found = 1;
  3442.             start_at += i * 2;
  3443.             break;
  3444.           }
  3445.         if (!found)
  3446.           start_at += 4096;
  3447.       } while (!found);
  3448.       break;
  3449.     default:
  3450.       size = 4;
  3451.       do
  3452.       { if (stop_at < start_at + size)
  3453.           break;
  3454.         buf_size = stop_at - start_at;
  3455.         if (buf_size > 4096)
  3456.           buf_size = 4096;
  3457.         read_child (start_at, read_buffer, buf_size);
  3458.         buf_size /= 4;
  3459.         mem_long = (word32 *)read_buffer;
  3460.         for (i = 0; i < buf_size; i++)
  3461.           if (mem_long[i] == search_for)
  3462.           { found = 1;
  3463.             start_at += i * 4;
  3464.             break;
  3465.           }
  3466.         if (!found)
  3467.           start_at += 4096;
  3468.       } while (!found);
  3469.       break;
  3470.   }
  3471.   if (!found)
  3472.     return (0);
  3473.   *(word32 *)(dialog_data[1].return_addr) = start_at + size;
  3474.   *(word32 *)(dialog_data[0].return_addr) = size;
  3475.   data_dump_origin = start_at;
  3476.   pane_pos = 0;
  3477.   redraw (0);
  3478.   return (1);
  3479. }
  3480. /* ---------------------------------------------------------------------- */
  3481. static void
  3482. search_memory (void)
  3483. { int size = 1, ret = 2;
  3484.   word32 start_at = areas[A_data].first_addr, search_for = 0;
  3485.  
  3486.   static DIALOG_ITEM dialog_data[] = {
  3487.     {"Size       :", 0 , 03, 1, format_int , eval_word, init_int , editor},
  3488.     {"Start at   :", 0 , 50, 1, format_addr, eval_word, init_addr, editor},
  3489.     {"Search for :", 0 , 10, 1, format_word, eval_word, init_word, editor},
  3490.     {0           , 0 , 0 , 0, 0          , 0        , 0        , 0       }
  3491.   };
  3492.   static BUTTON_ITEM button_data[] = {
  3493.     {" Search ", 1, action_search},
  3494.     {"  Done  ", 0, action_done  },
  3495.     {0         , 0, 0            }
  3496.   };                                               
  3497.  
  3498.   dialog_data[0].return_addr = (word32)&size;
  3499.   dialog_data[1].return_addr = (word32)&start_at;
  3500.   dialog_data[2].return_addr = (word32)&search_for;
  3501.   dialog ("Memory Search", dialog_data, button_data, &ret);
  3502. }
  3503. /* ---------------------------------------------------------------------- */
  3504. static void
  3505. port_io_add_action (DIALOG_ITEM d[], int action,
  3506.                     word32 port, word32 size, word32 data)
  3507. { unsigned char action_id, *p, fmt[ACTION_HIST_SIZE];
  3508.   memcpy ((char *)(d[1].return_addr), (char *)(d[2].return_addr), ACTION_HIST_SIZE);
  3509.   memcpy ((char *)(d[2].return_addr), (char *)(d[3].return_addr), ACTION_HIST_SIZE);
  3510.   memcpy ((char *)(d[3].return_addr), (char *)(d[4].return_addr), ACTION_HIST_SIZE);
  3511.   memcpy ((char *)(d[4].return_addr), (char *)(d[5].return_addr), ACTION_HIST_SIZE);
  3512.   p = (char *)(d[5].return_addr);
  3513.   action_id = p[strlen (p) + 1];
  3514.   action_id++;
  3515.   sprintf (fmt, "%%03d     %%s  0x%%04lx%%-%lds0x%%0%ldlx", 9 - size * 2, size * 2);
  3516.   sprintf (p, fmt, action_id, action ? "Out" : " In", port, " ", data);
  3517.   p[strlen (p) + 1] = action_id;
  3518. }
  3519. /* ---------------------------------------------------------------------- */
  3520. static int
  3521. action_outp (DIALOG_ITEM dialog_data[])
  3522. { int size = *(int *)(dialog_data[6].return_addr);
  3523.   word32 port = *(word32 *)(dialog_data[7].return_addr);
  3524.   word32 data = *(word32 *)(dialog_data[8].return_addr);
  3525.  
  3526.   port &= 0xffff;
  3527.   if (!port || !size)
  3528.     return (0);
  3529.   switch (size)
  3530.   { case 2:
  3531.       data &= 0xffff;
  3532.       outportw (port, data);
  3533.       break;
  3534.     case 4:
  3535.       outportl (port, data);
  3536.       break;
  3537.     default:
  3538.       data &= 0xff;
  3539.       outportb (port, data);
  3540.       break;
  3541.   }
  3542.   port_io_add_action (dialog_data, 1, port, size, data);
  3543.   return (1);
  3544. }
  3545. /* ---------------------------------------------------------------------- */
  3546. static int
  3547. action_inp (DIALOG_ITEM dialog_data[])
  3548. { int size = *(int *)(dialog_data[6].return_addr);
  3549.   word32 port = *(word32 *)(dialog_data[7].return_addr);
  3550.   word32 data;
  3551.  
  3552.   port &= 0xffff;
  3553.   if (!port || !size)
  3554.     return (0);
  3555.   switch (size)
  3556.   { case 2:
  3557.       data = inportw (port) & 0xffff;
  3558.       break;
  3559.     case 4:
  3560.       data = inportl (port);
  3561.       break;
  3562.     default:
  3563.       *(int *)(dialog_data[6].return_addr) = 1;
  3564.       size = 1;
  3565.       data = inportb (port) & 0xff;
  3566.       break;
  3567.   }
  3568.   *(word32 *)(dialog_data[8].return_addr) = data;
  3569.   port_io_add_action (dialog_data, 0, port, size, data);
  3570.   return (1);
  3571. }
  3572. /* ---------------------------------------------------------------------- */
  3573. static void
  3574. read_write_port (void)
  3575. { int ret = 11;
  3576.   static int size = 1;
  3577.   static word32 port = 0x20, data = 0;
  3578.   static char last_act_0[ACTION_HIST_SIZE] = " ID  Action    Port      Value";
  3579.   static char last_act_1[ACTION_HIST_SIZE] = "---     ---  ------ ----------\0";
  3580.   static char last_act_2[ACTION_HIST_SIZE] = "---     ---  ------ ----------\0";
  3581.   static char last_act_3[ACTION_HIST_SIZE] = "---     ---  ------ ----------\0";
  3582.   static char last_act_4[ACTION_HIST_SIZE] = "---     ---  ------ ----------\0";
  3583.   static char last_act_5[ACTION_HIST_SIZE] = "---     ---  ------ ----------\0\377";
  3584.  
  3585.   static DIALOG_ITEM dialog_data[] = {
  3586.     {"History:", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
  3587.     {"        ", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
  3588.     {"        ", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
  3589.     {"        ", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
  3590.     {"        ", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
  3591.     {"        ", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
  3592.     {"Size   :", 0, 03, 1, format_int , eval_word, init_int , editor},
  3593.     {"Port   :", 0, 10, 1, format_word, eval_word, init_word, editor},
  3594.     {"Data   :", 0, 10, 1, format_word, eval_word, init_word, editor},
  3595.     {0         , 0, 0 , 0, 0          , 0        , 0        , 0     }
  3596.   };
  3597.   static BUTTON_ITEM button_data[] = {
  3598.     {"  Out   ", 1, action_outp},
  3599.     {"   In   ", 1, action_inp },
  3600.     {"  Done  ", 0, action_done},
  3601.     {0         , 0, 0          }
  3602.   };                                               
  3603.  
  3604.   dialog_data[0].return_addr = (word32)last_act_0;
  3605.   dialog_data[1].return_addr = (word32)last_act_1;
  3606.   dialog_data[2].return_addr = (word32)last_act_2;
  3607.   dialog_data[3].return_addr = (word32)last_act_3;
  3608.   dialog_data[4].return_addr = (word32)last_act_4;
  3609.   dialog_data[5].return_addr = (word32)last_act_5;
  3610.   dialog_data[6].return_addr = (word32)&size;
  3611.   dialog_data[7].return_addr = (word32)&port;
  3612.   dialog_data[8].return_addr = (word32)&data;
  3613.   dialog ("Port IO", dialog_data, button_data, &ret);
  3614. }
  3615. /* ---------------------------------------------------------------------- */
  3616. static MENU_ITEM Data_Local_Menu[] = {
  3617.        {"Current Highlighted Item            ", 1        , ""     , 0},
  3618.        {"Toggle data write breakpoint     ~w~", ITEM_TYPE, "w"    , 0},
  3619.        {"Toggle read/write breakpoint     ~r~", ITEM_TYPE, "r"    , 0},
  3620.        {"Display data at EIP              ~i~", ITEM_TYPE, "i"    , 0},
  3621.        {"Display data at ESP              ~s~", ITEM_TYPE, "s"    , 0},
  3622.        {"Display data at current pointer  ~*~", ITEM_TYPE, "*"    , 0},
  3623.        {"Display data at last address(es) ~@~", ITEM_TYPE, "@"    , 0},
  3624.        {"Move pane's origin left        ~M b~", ITEM_TYPE, "\033b", 0},
  3625.        {"Move pane's origin right       ~M f~", ITEM_TYPE, "\033f", 0},
  3626.        {"Display as bytes                 ~b~", ITEM_TYPE, "b"    , 0},
  3627.        {"Display as words                 ~h~", ITEM_TYPE, "h"    , 0},
  3628.        {"Display as dwords                ~f~", ITEM_TYPE, "f"    , 0},
  3629.        {"Port access                      ~p~", ITEM_TYPE, "p"    , 0},
  3630.        {"Modify data at cursor         ~^C m~", ITEM_TYPE, "\3m"  , 0},
  3631.        {"Undo modification(s)          ~^C u~", ITEM_TYPE, "\3u"  , 0},
  3632.        {"Search memory                 ~^C s~", ITEM_TYPE, "\3s"  , 0},
  3633.        {"Data structure supports          ~n~", ITEM_TYPE, "n"    , 0},
  3634.        {0                                     , 0        , ""     , 0}
  3635. };                                        
  3636. static word32 old_dump_address[5] = {0, 0, 0, 0, 0};
  3637. /* ---------------------------------------------------------------------- */
  3638. static void
  3639. data_pane_command (int key)
  3640. { word32 v = data_dump_origin + pane_pos;
  3641.   int res, ok, bad = 0;
  3642.   char *p, *p0, q, s[2];
  3643.   
  3644.   if (key == 0)
  3645.   { pop_menu (Data_Local_Menu, "Data", 1, rows - 19, &res);
  3646.     control_c = 0;
  3647.     control_x = 0;
  3648.     escaped   = 0;
  3649.     switch (res)
  3650.     { case 1: 
  3651.         key = 'w';
  3652.         break;
  3653.       case 2:        
  3654.         key = 'r';
  3655.         break;
  3656.       case 3:        
  3657.         key = 'i';
  3658.         break;
  3659.       case 4:        
  3660.         key = 's';
  3661.         break;
  3662.       case 5:        
  3663.         key = '*';
  3664.         break;
  3665.       case 6:        
  3666.         key = '@';
  3667.         break;
  3668.       case 7:    
  3669.         escaped = 1;    
  3670.         key = 'b';
  3671.         break;
  3672.       case 8:        
  3673.         escaped = 1;    
  3674.         key = 'f';
  3675.         break;
  3676.       case 9:        
  3677.         key = 'b';
  3678.         break;
  3679.       case 10:        
  3680.         key = 'h';
  3681.         break;
  3682.       case 11:        
  3683.         key = 'f';
  3684.         break;
  3685.       case 12:        
  3686.         key = 'p';
  3687.         break;
  3688.       case 13:   
  3689.         control_c = 1;
  3690.         key = 'm';
  3691.         break;
  3692.       case 14:
  3693.         control_c = 1;
  3694.         key = 'u';
  3695.         break;
  3696.     case 15:
  3697.         control_c = 1;
  3698.         key = 's';
  3699.     case 16:
  3700.         key = 'n';
  3701.         break;
  3702.     }
  3703.   }
  3704.   if (control_x)
  3705.   { switch (key)
  3706.     { case '/':                            /* Save to register      */
  3707.         key = my_get_char ("Save address to which register (0..A..z)? ");
  3708.         if (key >= '0' && key <= 'z')
  3709.            registers[key - '0'] = v;
  3710.         break;
  3711.       case 'j':                            /* Load from register    */
  3712.       case 'J':       
  3713.         key = my_get_char ("Load address from which register (0..A..z)? ");
  3714.         if (key >= '0' && key <= 'z')
  3715.           if (registers[key - '0'])
  3716.           { data_dump_origin = registers[key - '0'];
  3717.             pane_pos = 0;
  3718.           }
  3719.         break;
  3720.     }           
  3721.   }                                                
  3722.   if (control_c)
  3723.   { switch (key)
  3724.     { case 'm':
  3725.       case 'M':
  3726.       { if (!my_read_string ("New value: "))
  3727.         { p = read_buffer;
  3728.           do
  3729.           { while (*p == ' ') p++;
  3730.             switch (*p)
  3731.             { case '\0':
  3732.                 break;
  3733.               case '\'':
  3734.               case '"':
  3735.                 if (data_dump_size != 1)
  3736.                 { *p = 0;
  3737.                   message (CL_Error, "Strings must be entered in byte mode");
  3738.                   break;
  3739.                 }
  3740.                 q = *p++;
  3741.                 p0 = p;
  3742.                 while (*p != q && *p) 
  3743.                   p++;
  3744.                 if (*p)
  3745.                 { while (p0 != p)
  3746.                   { if (valid_addr (v, 1))
  3747.                       write_child (v, p0, 1);
  3748.                     else
  3749.                       bad = 1;
  3750.                     p0++, v++;
  3751.                   }
  3752.                   if (q == '"')
  3753.                   { if (valid_addr (v, 1))
  3754.                     { q = 0;
  3755.                       write_child (v, &q, 1);
  3756.                       q = '"';
  3757.                     }
  3758.                     else
  3759.                       bad = 1;
  3760.                     v++;
  3761.                   }
  3762.                   p++;
  3763.                 }
  3764.                 else
  3765.                   message (CL_Error, "String constant not terminated");
  3766.                 break;
  3767.               default:
  3768.                 p0 = p;
  3769.                 while (*p != ',' && *p)
  3770.                   p++;
  3771.                 q = *p;
  3772.                 *p = 0;
  3773.                 res = parse_expression (4, p0, &ok);
  3774.                 if (ok == ParseError_ok)
  3775.                 { *p = q;
  3776.                   if (valid_addr (v, data_dump_size))
  3777.                   { word32 u_val;
  3778.                     read_child (v, &u_val, data_dump_size);
  3779.                     put_undo (&data_undo, v, u_val, data_dump_size);
  3780.                     write_child (v, &res, data_dump_size);
  3781.                   } else
  3782.                     bad = 1;
  3783.                   v += data_dump_size;
  3784.                 } else
  3785.                 { message (CL_Error, "Invalid expression: %s", p0);
  3786.                   bad = 1;
  3787.                 }
  3788.             }
  3789.             if (*p == ',') 
  3790.               p++;
  3791.           } while (*p);
  3792.           if (bad)
  3793.             message (CL_Error, "Part of the data could not be written");
  3794.           else
  3795.             message (CL_Info, "Memory modified.");
  3796.         }
  3797.         break;
  3798.       } 
  3799.       case 'u':
  3800.       case 'U':                                                     
  3801.       { word32 u_addr, u_val, old_val = 0;
  3802.         int u_size;
  3803.  
  3804.         if (get_undo (&data_undo, &u_addr, &u_val, &u_size))
  3805.         { read_child  (u_addr, &old_val, u_size);
  3806.           write_child (u_addr, &u_val, u_size);  
  3807.           message (CL_Msg, 
  3808.                    "%d byte(s) at %08lx has been undone from %08lx to %08lx",
  3809.                    u_size, u_addr, old_val, u_val);
  3810.         }
  3811.         break;     
  3812.       }
  3813.       case 's':
  3814.       case 'S':
  3815.          search_memory ();
  3816.          break;
  3817.     }
  3818.   }
  3819.   if (escaped)
  3820.   { switch (key)
  3821.     { case 'b':
  3822.       case 'B':
  3823.         data_dump_origin--;
  3824.         break;
  3825.       case 'f':
  3826.       case 'F':
  3827.         data_dump_origin++;
  3828.         break; 
  3829.       case 'v':
  3830.       case 'V':
  3831.         escaped = 0;
  3832.         key = K_PageUp;
  3833.         break;
  3834.     }
  3835.   }
  3836.   if (!(escaped || control_c || control_x))
  3837.     switch (key)
  3838.     { case K_Up:
  3839.       case K_EUp:
  3840.       case K_Control_P:
  3841.         if (pane_pos >= 8)
  3842.           pane_pos -= 8;
  3843.         else
  3844.           data_dump_origin -= 8;
  3845.         break;
  3846.       case K_Down:
  3847.       case K_EDown:
  3848.       case K_Control_N:
  3849.         if (v + 8 <= data_dump_last)
  3850.           pane_pos += 8;
  3851.         else
  3852.           data_dump_origin += 8;
  3853.         break;
  3854.       case K_Left:
  3855.       case K_ELeft:
  3856.       case K_Control_B:
  3857.         if (pane_pos > 0)
  3858.           pane_pos -= data_dump_size;
  3859.         else
  3860.           data_dump_origin -= 8, pane_pos = 8 - data_dump_size;
  3861.         break;
  3862.       case K_Right:
  3863.       case K_ERight:
  3864.       case K_Control_F:
  3865.         if (v + data_dump_size <= data_dump_last)
  3866.           pane_pos += data_dump_size;
  3867.         else
  3868.           data_dump_origin += 8, pane_pos -= (8 - data_dump_size);
  3869.         break;
  3870.       case K_PageUp:
  3871.       case K_EPageUp:
  3872.         data_dump_origin -= (data_dump_last + 1 - data_dump_origin);
  3873.         break;
  3874.       case K_PageDown:
  3875.       case K_EPageDown:
  3876.       case K_Control_V:
  3877.         data_dump_origin = data_dump_last + 1;
  3878.         break;
  3879.       case 's':
  3880.       case 'S':
  3881.         data_dump_origin = a_tss.tss_esp;
  3882.         pane_pos = 0;
  3883.         break;
  3884.       case 'i':
  3885.       case 'I':
  3886.         data_dump_origin = a_tss.tss_eip;
  3887.         data_dump_size = 1;
  3888.         pane_pos = 0;
  3889.         break;                     
  3890.       case '*':  
  3891.         if (valid_addr (v, 4))
  3892.         { for (res = 1; res < 5; res++)
  3893.             old_dump_address[res - 1] = old_dump_address[res];
  3894.           old_dump_address[4] = data_dump_origin + pane_pos;
  3895.           read_child (v, &data_dump_origin, 4);
  3896.           pane_pos = 0;
  3897.         } else
  3898.           message (CL_Error, "Pointer points to an invalid address.");
  3899.         break;
  3900.       case '@':
  3901.         if (!old_dump_address[4])
  3902.            old_dump_address[4] = data_dump_origin;
  3903.         data_dump_origin = old_dump_address[4]; 
  3904.         pane_pos = 0;
  3905.         for (res = 4; res > 0; res--)
  3906.            old_dump_address[res] = old_dump_address[res - 1];
  3907.         old_dump_address[0] = data_dump_origin;
  3908.         break;
  3909.       case 'b':
  3910.       case 'B':
  3911.         data_dump_size = 1;
  3912.         break;
  3913.       case 'h':
  3914.       case 'H':
  3915.         data_dump_size = 2;
  3916.         break;
  3917.       case 'f':
  3918.       case 'F':
  3919.         data_dump_size = 4;
  3920.         break;
  3921.       case 'n':
  3922.       case 'N':               
  3923.         if (!running_xsupport)
  3924.         { running_xsupport = 1;
  3925.           if (extern_data_support(v))
  3926.             running_xsupport = 0;
  3927.           break;
  3928.         }
  3929.       case 'p':
  3930.       case 'P':
  3931.         read_write_port();
  3932.         break;
  3933.       case 'w':
  3934.       case 'W':
  3935.         res = get_breakpoint (BP_Write, data_dump_size, v);
  3936.         if (res == -1)
  3937.           set_breakpoint (BP_Write, data_dump_size, v);
  3938.         else
  3939.           reset_breakpoint (res);
  3940.         break;
  3941.       case 'r':
  3942.       case 'R':
  3943.         res = get_breakpoint (BP_Read, data_dump_size, v);
  3944.         if (res == -1)
  3945.           set_breakpoint (BP_Read, data_dump_size, v);
  3946.         else
  3947.           reset_breakpoint (res);
  3948.         break;
  3949.       case 'e':
  3950.       case 'E':
  3951.         res = get_breakpoint (BP_Read, -1, v);
  3952.         if (res == -1)
  3953.         { res = set_breakpoint (BP_Read, data_dump_size, v);
  3954.           if (edit_breakpoint(res))
  3955.             reset_breakpoint (res);
  3956.         } else
  3957.           edit_breakpoint (res);
  3958.         break;
  3959.       default:
  3960.         if ((key == '_') || (key == '%') ||
  3961.             (key == '(') || (key >= '0' && key <= '9'))
  3962.         { s[0] = key; s[1] = '\0';
  3963.           if (last_addr[0])
  3964.             ok = !read_string (last_addr);
  3965.           else
  3966.             ok = !read_string (key == '=' ? "" : s);
  3967.           strcpy (last_addr, read_buffer);
  3968.           if (ok)
  3969.           { p = read_buffer;
  3970.             while (*p != 0 && *p == ' ')
  3971.               p++;
  3972.             if (*p)
  3973.             { res = parse_expression (4, p, &ok);
  3974.               if (ok == ParseError_ok)
  3975.               { data_dump_origin = res;
  3976.                 pane_pos = 0;
  3977.                 for (res = 1; res < 5; res++)
  3978.                   old_dump_address[res - 1] = old_dump_address[res];
  3979.                 old_dump_address[4] = data_dump_origin;
  3980.                 last_addr[0] = 0;
  3981.                 message (CL_Info, "Found address %s.", p);
  3982.               }                                  
  3983.               else
  3984.                 message (CL_Error, "Bad address: %s", p);
  3985.             }
  3986.           }
  3987.         }
  3988.         break;
  3989.       }
  3990.   pane_pos &= ~(data_dump_size - 1);
  3991.   redraw (0);
  3992. }
  3993. /* ---------------------------------------------------------------------- */
  3994. static MENU_ITEM Npx_Local_Menu[] = {
  3995.        {"Current Item            ", 1        , ""   , 0},
  3996.        {"Empty register    ~^C e~", ITEM_TYPE, "\3e", 0},
  3997.        {"Zero register     ~^C z~", ITEM_TYPE, "\3z", 0},
  3998.        {"Negate register   ~^C n~", ITEM_TYPE, "\3n", 0},
  3999.        {"Modify register   ~^C m~", ITEM_TYPE, "\3m", 0},
  4000.        {"Undo modification ~^C u~", ITEM_TYPE, "\3u", 0},
  4001.        {0                         , 0        , ""   , 0}
  4002. };                                                     
  4003. /* ---------------------------------------------------------------------- */
  4004. static void
  4005. npx_pane_command (int key)
  4006. { NPX *del_npx;
  4007.   int reg = pane_pos - 3, rotreg = 0, tag = 0;
  4008.   int regp = (reg >= 0);
  4009.   int b;
  4010.  
  4011.   save_npx ();      
  4012.   if (regp)
  4013.   { rotreg = (reg + (npx.status >> 11)) & 7;
  4014.     tag = (npx.tag >> (rotreg * 2)) & 3;
  4015.   }
  4016.  
  4017.   if (key == 0)
  4018.   { pop_menu (Npx_Local_Menu, "Npx", 1, 3, &b);
  4019.     control_c = 1;
  4020.     control_x = 0;
  4021.     escaped   = 0;
  4022.     switch (b)
  4023.     { case 1:
  4024.         key = 'e';
  4025.         break;
  4026.       case 2:             
  4027.         key = 'z';
  4028.         break;
  4029.       case 3:             
  4030.         key = 'n';
  4031.         break;
  4032.       case 4:    
  4033.         key = 'm';
  4034.         break;
  4035.       case 5:    
  4036.         key = 'u';
  4037.         break;
  4038.     }                                      
  4039.   }           
  4040.   if (control_c)
  4041.   { switch (key)
  4042.     { case 'e':
  4043.       case 'E':
  4044.         if (regp)
  4045.         { tag = 3;                     
  4046.           del_npx = malloc (sizeof (NPX));
  4047.           memcpy (del_npx, &npx, sizeof (NPX));
  4048.           put_undo (&npx_undo, 1, (word32)del_npx, 1);
  4049.       memset (&npx.reg[reg], 0, sizeof (NPXREG));
  4050.     }
  4051.         break;
  4052.       case 'z':
  4053.       case 'Z':
  4054.         if (regp)
  4055.         { tag = 1;
  4056.           del_npx = malloc (sizeof (NPX));
  4057.           memcpy (del_npx, &npx, sizeof (NPX));
  4058.           put_undo (&npx_undo, 1, (word32)del_npx, 1);
  4059.       memset (&npx.reg[reg], 0, sizeof (NPXREG));
  4060.     }
  4061.         break;
  4062.       case 'n':
  4063.       case 'N':
  4064.         if (regp)
  4065.         { del_npx = malloc (sizeof (NPX));
  4066.           memcpy (del_npx, &npx, sizeof (NPX));
  4067.           put_undo (&npx_undo, 1, (word32)del_npx, 1);
  4068.           npx.reg[reg].sign = !npx.reg[reg].sign;
  4069.         }
  4070.         break;
  4071.       case 'm':
  4072.       case 'M':
  4073.       { char *p, *endp;
  4074.         double d;
  4075.  
  4076.         if (!my_read_string ("New value: "))
  4077.         { p = read_buffer;
  4078.           del_npx = malloc (sizeof (NPX));
  4079.           memcpy (del_npx, &npx, sizeof (NPX));
  4080.           put_undo (&npx_undo, 1, (word32)del_npx, 1);
  4081.           while (*p == ' ')
  4082.             p++;
  4083.           if (*p == '\0')
  4084.             break;
  4085.           strlwr (p);
  4086.           if (strcmp (p, "+inf") == 0
  4087.               || strcmp (p, "inf") == 0
  4088.               || strcmp (p, "-inf") == 0)
  4089.           { tag = 2;
  4090.             npx.reg[reg].exponent = 0x7fff;
  4091.             npx.reg[reg].sig3 = 0x8000;
  4092.             npx.reg[reg].sig2
  4093.             = npx.reg[reg].sig1
  4094.             = npx.reg[reg].sig0 = 0;
  4095.             npx.reg[reg].sign = (*p == '-');
  4096.           } else
  4097.           { d = strtod (p, &endp);
  4098.             if (*p != '\0' && *endp)
  4099.               message (CL_Error, "Expression not understood");
  4100.             else
  4101.             { tag = (d == 0.0);
  4102.               *((long double *)(npx.reg + reg)) = (long double) d;
  4103.               npx.reg[reg].sign = (*p == '-'); /* for -Zero */
  4104.             }
  4105.           }
  4106.         }
  4107.         break;
  4108.       }
  4109.       case 'u':
  4110.       case 'U':
  4111.       { word32 u_addr, u_val;
  4112.         int u_size;
  4113.         if (get_undo (&npx_undo, &u_addr, &u_val, &u_size))
  4114.         { del_npx = (NPX *)u_val;
  4115.           memcpy (&npx, del_npx, sizeof (NPX));
  4116.         }
  4117.         break;                                             
  4118.       }
  4119.     }
  4120.   }
  4121.   if (!(escaped || control_c || control_x))
  4122.     switch (key)
  4123.     { case K_Left:
  4124.       case K_ELeft:
  4125.       case K_Up:
  4126.       case K_EUp:
  4127.       case K_Control_P:
  4128.       case K_Control_B:
  4129.         if (pane_pos > 0) pane_pos--;
  4130.         break;
  4131.       case K_Right:
  4132.       case K_ERight:
  4133.       case K_Down:
  4134.       case K_EDown:    
  4135.       case K_Control_N:
  4136.       case K_Control_F:
  4137.         if ((pane_pos < 10) && (pane_pos < toplines - 2)) pane_pos++;
  4138.         break;
  4139.     }
  4140.   if (regp)
  4141.     npx.tag = (npx.tag & ~(3 << (rotreg * 2))) | (tag << (rotreg * 2));
  4142.   load_npx ();
  4143.   redraw (0);
  4144. }
  4145. /* ---------------------------------------------------------------------- */
  4146. static MENU_ITEM Stack_Local_Menu[] = {
  4147.        {"Current Highlighted", 1        , ""    , 0},
  4148.        {"Goto function  ~^M~", ITEM_TYPE, "\015", 0},
  4149.        {0                    , 0        , ""    , 0}
  4150. };                                                     
  4151. /* ---------------------------------------------------------------------- */
  4152. static void
  4153. stack_pane_command (int key)
  4154. {
  4155.   int b;
  4156.  
  4157.   if (key == 0)
  4158.   { pop_menu (Stack_Local_Menu, "Stack", 1, 3, &b);
  4159.     control_c = 0;
  4160.     control_x = 0;
  4161.     escaped   = 0;
  4162.     switch (b)
  4163.     { case 1:
  4164.         key = K_Return;
  4165.         break;
  4166.     }  
  4167.   }
  4168.   if (!(escaped || control_c || control_x))
  4169.     switch (key)
  4170.     { case K_Left:
  4171.       case K_ELeft:
  4172.       case K_Up:
  4173.       case K_EUp:
  4174.       case K_Control_P:
  4175.       case K_Control_B:
  4176.         if (pane_pos > 0)
  4177.           pane_pos--;
  4178.         else
  4179.           if (stack_dump_origin)
  4180.             stack_dump_origin--;
  4181.         break;
  4182.       case K_Right:
  4183.       case K_ERight:
  4184.       case K_Down:
  4185.       case K_EDown:
  4186.       case K_Control_N:
  4187.       case K_Control_F:
  4188.         if (pane_pos < stack_dump_last)
  4189.           pane_pos++;
  4190.         else
  4191.           if (stack_dump_more)
  4192.             stack_dump_origin++;
  4193.         break;
  4194.       case K_Return:
  4195.         code_pane_goto (stack_dump_pos[pane_pos]);
  4196.         stack_pane_active = 0;
  4197.         code_pane_active = 1;
  4198.         pane = 0;
  4199.         break;
  4200.     }
  4201.   redraw (0);
  4202. }
  4203. /* ---------------------------------------------------------------------- */
  4204. static MENU_ITEM Info_Local_Menu[] = {
  4205.        {"Current Highlighted Item", 1        , "", 0},
  4206.        {"No command available    ", ITEM_TYPE, "", 0},
  4207.        {0                         , 0        , "", 0}
  4208. };                                                     
  4209. /* ---------------------------------------------------------------------- */
  4210. static void
  4211. info_pane_command (int key)
  4212. { int b;
  4213.   /* No keys recognized.  */
  4214.         
  4215.   if (key == 0)
  4216.   { pop_menu (Info_Local_Menu, "Info", 1, 3, &b);
  4217.   }
  4218.   redraw (0);
  4219. }
  4220. /* ---------------------------------------------------------------------- */
  4221. static void
  4222. fullscr_listwild_handler (word32 sym_num)
  4223. { whereis_pane_sym = realloc (whereis_pane_sym,
  4224.                  (++whereis_sym_count) * sizeof (word32));
  4225.   whereis_pane_sym[whereis_sym_count - 1] = sym_num;
  4226. }
  4227. /* ---------------------------------------------------------------------- */
  4228. static void
  4229. init_whereis_sym (void)
  4230. { char *p;
  4231.  
  4232.   if (!my_read_string ("Search for: ") && read_buffer[0] != '\0')
  4233.   { whereis_pane_sym = realloc (whereis_pane_sym, 0);
  4234.     p = read_buffer;
  4235.     while (*p == ' ') p++;
  4236.     syms_listwild (p, &fullscr_listwild_handler);
  4237.     pane_pos = whereis_origin = 0;
  4238.     if (whereis_sym_count >= 10)
  4239.       message (CL_Info, "There were %d symbols that matched",
  4240.                 whereis_sym_count);
  4241.   }        
  4242.   redraw (0);
  4243. }
  4244. /* ---------------------------------------------------------------------- */
  4245. static MENU_ITEM WhereIs_Local_Menu[] = {
  4246.        {"Current Highlighted Item    ", 1        , ""     , 0},
  4247.        {"Goto beginning of list ~M <~", ITEM_TYPE, "\033<", 0},
  4248.        {"Goto end of list       ~M >~", ITEM_TYPE, "\033>", 0},
  4249.        {"Search for symbol(s)        ", ITEM_TYPE, ""     , 0},
  4250.        {0                             , 0        , ""     , 0}
  4251. };                                                     
  4252. /* ---------------------------------------------------------------------- */
  4253. static void
  4254. whereis_pane_command (int key)
  4255. {
  4256.   int no = whereis_origin + pane_pos;
  4257.   int b;
  4258.  
  4259.   if (key == 0)
  4260.   { pop_menu (WhereIs_Local_Menu, "WhereIs", 1, 3, &b);
  4261.     control_c = 0;
  4262.     control_x = 0;
  4263.     escaped   = 0;
  4264.     switch (b)
  4265.     { case 1:
  4266.         key = K_Home;
  4267.         break;
  4268.       case 2:             
  4269.         key = K_End;
  4270.         break;
  4271.       case 3:
  4272.         key = '_';
  4273.         break;
  4274.     }  
  4275.   }
  4276.   if (escaped)
  4277.   { switch (key)
  4278.     { case 'v':
  4279.       case 'V':
  4280.         escaped = 0;
  4281.         key = K_PageUp;
  4282.         break;
  4283.       case '>':
  4284.         escaped = 0;
  4285.         key = K_End;
  4286.         break;
  4287.       case '<':
  4288.         escaped = 0;
  4289.         key = K_Home;
  4290.         break;
  4291.     }
  4292.   }
  4293.   if (!(escaped || control_c || control_x))
  4294.   { switch (key)
  4295.     { case K_Left:
  4296.       case K_ELeft:
  4297.       case K_Up:
  4298.       case K_EUp:   
  4299.       case K_Control_P:
  4300.       case K_Control_B:
  4301.         if (pane_pos > 0)
  4302.           pane_pos--;
  4303.         else
  4304.           if (whereis_origin)
  4305.             whereis_origin--;
  4306.         break;
  4307.       case K_Right:
  4308.       case K_ERight:
  4309.       case K_Down:
  4310.       case K_EDown:    
  4311.       case K_Control_N:
  4312.       case K_Control_F:
  4313.         if (no < whereis_sym_count - 1)
  4314.           if (pane_pos < toplines - 2)
  4315.             pane_pos++;
  4316.         else
  4317.             whereis_origin++;
  4318.         break;
  4319.       case K_Home:
  4320.       case K_EHome:
  4321.         pane_pos = whereis_origin = 0;
  4322.         break;
  4323.       case K_End:
  4324.       case K_EEnd:
  4325.         if (whereis_sym_count > toplines - 1)
  4326.         { whereis_origin = whereis_sym_count - toplines;
  4327.           pane_pos = toplines - 2;
  4328.         }
  4329.         else
  4330.         { whereis_origin = 0;
  4331.           pane_pos = whereis_sym_count ? whereis_sym_count - 1 : 0;
  4332.         }
  4333.         break;
  4334.       case K_PageDown:
  4335.       case K_EPageDown:
  4336.       case K_Control_V:
  4337.         if (whereis_origin + toplines < whereis_sym_count)
  4338.         { whereis_origin += toplines - 1;
  4339.           if (whereis_origin + pane_pos >= whereis_sym_count)
  4340.           pane_pos = whereis_sym_count - 1 - whereis_origin;
  4341.         }
  4342.         break;
  4343.       case K_PageUp:
  4344.       case K_EPageUp:
  4345.         if (whereis_origin > toplines)
  4346.           whereis_origin -= toplines;
  4347.         else
  4348.           whereis_origin = pane_pos = 0;
  4349.         break;
  4350.       case K_Return:
  4351.         if (whereis_sym_count)
  4352.         { char typ;
  4353.           unsigned long ul;
  4354.  
  4355.           syms_get (whereis_pane_sym[no], &ul, &typ);
  4356.           switch (toupper (typ))
  4357.           { case 'T':
  4358.               code_pane_goto (ul);
  4359.               whereis_pane_active = 0;
  4360.               code_pane_active = 1;
  4361.               pane = 0;
  4362.               break;
  4363.             case 'B':
  4364.             case 'D':
  4365.              data_dump_origin = ul;
  4366.              pane_positions[4] = 0;
  4367.              break;
  4368.           }
  4369.         }
  4370.         break;
  4371.       default:
  4372.         if ((key == '_') || (key >= '0' && key <= '9'))
  4373.         { char s[2], *p;
  4374.  
  4375.           s[0] = key; s[1] = '\0';
  4376.           if (!read_string (key == '=' ? "" : s) && read_buffer[0] != '\0')
  4377.           { whereis_pane_sym = realloc (whereis_pane_sym, 0);
  4378.             whereis_sym_count = 0;
  4379.             p = read_buffer;
  4380.             while (*p == ' ') p++;
  4381.             syms_listwild (p, &fullscr_listwild_handler);
  4382.             pane_pos = whereis_origin = 0;
  4383.             if (whereis_sym_count >= 10)
  4384.               message (CL_Info, "There were %d symbols that matched",
  4385.                        whereis_sym_count);
  4386.           }
  4387.         }
  4388.     }
  4389.   }
  4390.   redraw (0);
  4391. }
  4392. /* ---------------------------------------------------------------------- */
  4393. static MENU_ITEM Module_Local_Menu[] = {
  4394.        {"Current Highlighted Item", 1        , "", 0},
  4395.        {"No command available    ", ITEM_TYPE, "", 0},
  4396.        {0                         , 0        , "", 0}
  4397. };                                                     
  4398. /* ---------------------------------------------------------------------- */
  4399. static void
  4400. module_pane_command(int key)
  4401. {
  4402.   int no = module_origin + pane_pos;
  4403.   int b;
  4404.  
  4405.   if (key == 0)
  4406.   { pop_menu (Module_Local_Menu, "Module", 1, 3, &b);
  4407.   }
  4408.   if (escaped)
  4409.   { switch (key)
  4410.     { case 'v':
  4411.       case 'V':
  4412.         escaped = 0;
  4413.         key = K_PageUp;
  4414.         break;
  4415.       case '>':
  4416.         escaped = 0;
  4417.         key = K_End;
  4418.         break;
  4419.       case '<':
  4420.         escaped = 0;
  4421.         key = K_Home;
  4422.         break;
  4423.     }
  4424.   }
  4425.   if (!(escaped || control_c || control_x))
  4426.   { switch (key)
  4427.     { case K_Left:
  4428.       case K_ELeft:
  4429.       case K_Up:
  4430.       case K_EUp:
  4431.         if (pane_pos > 0)
  4432.           pane_pos--;
  4433.         else
  4434.           if (module_origin)
  4435.             module_origin--;
  4436.         break;
  4437.       case K_Right:
  4438.       case K_ERight:
  4439.       case K_Down:
  4440.       case K_EDown:
  4441.         if (no < module_text_count - 1)
  4442.           if (pane_pos < toplines - 2)
  4443.             pane_pos++;
  4444.           else
  4445.             module_origin++;
  4446.         break;
  4447.       case K_Home:
  4448.       case K_EHome:
  4449.         pane_pos = module_origin = 0;
  4450.         break;
  4451.       case K_End:
  4452.       case K_EEnd:
  4453.         if (module_text_count > toplines - 1)
  4454.         { module_origin = module_text_count - toplines;
  4455.           pane_pos = toplines - 2;
  4456.         }
  4457.         else
  4458.         { module_origin = 0;
  4459.           pane_pos = module_text_count ? module_text_count - 1 : 0;
  4460.         }
  4461.         break;
  4462.       case K_PageDown:
  4463.       case K_EPageDown:
  4464.       case K_Control_V:
  4465.         if (module_origin + toplines <= module_text_count)
  4466.         { module_origin += toplines - 1;
  4467.           if (module_origin + pane_pos >= module_text_count)
  4468.             pane_pos = module_text_count - 1 - module_origin;
  4469.         }
  4470.         break;
  4471.       case K_PageUp:
  4472.       case K_EPageUp:
  4473.         if (module_origin > toplines - 1)
  4474.           module_origin -= toplines - 1;
  4475.         else
  4476.           module_origin = pane_pos = 0;
  4477.         break;
  4478.       case K_Return:
  4479.         if (no)
  4480.           if (!my_read_string ("Line number: "))
  4481.           { unsigned long ul;
  4482.             char *endp;
  4483.   
  4484.             ul = strtoul (read_buffer, &endp, 0);
  4485.             ul = get_linenum (no - 1, ul);
  4486.             code_pane_goto (ul);
  4487.             module_pane_active = 0;
  4488.             code_pane_active = 1;
  4489.             pane = 0;
  4490.           }
  4491.         break;
  4492.       case K_Control_G:
  4493.         module_pane_active = 0;
  4494.         code_pane_active = 1;
  4495.         pane = 0;
  4496.         break;
  4497.     }
  4498.   }
  4499.   redraw (0);
  4500. }
  4501. /* ---------------------------------------------------------------------- */
  4502. static MENU_ITEM Help_Local_Menu[] = {
  4503.        {"Current Highlighted Item", 1        , "", 0},
  4504.        {"No command available    ", ITEM_TYPE, "", 0},
  4505.        {0                         , 0        , "", 0}
  4506. };                                                     
  4507. /* ---------------------------------------------------------------------- */
  4508. static void
  4509. help_pane_command(int key)
  4510. {
  4511.   int no = help_origin + pane_pos;
  4512.   int b;
  4513.  
  4514.   if (key == 0)
  4515.   { pop_menu (Help_Local_Menu, "Help", 1, 3, &b);
  4516.   }
  4517.   if (escaped)
  4518.   { switch (key)
  4519.     { case 'v':
  4520.       case 'V':
  4521.         escaped = 0;
  4522.         key = K_PageUp;
  4523.         break;
  4524.       case '>':
  4525.         escaped = 0;
  4526.         key = K_End;
  4527.         break;
  4528.       case '<':
  4529.         escaped = 0;
  4530.         key = K_Home;
  4531.         break;
  4532.     }
  4533.   }
  4534.   if (!(escaped || control_c || control_x))
  4535.   { switch (key)
  4536.     { case K_Left:
  4537.       case K_ELeft:
  4538.       case K_Up:
  4539.       case K_EUp:
  4540.       case K_Control_P:
  4541.       case K_Control_B:
  4542.         if (pane_pos > 0)
  4543.           pane_pos--;
  4544.         else
  4545.           if (help_origin)
  4546.             help_origin--;
  4547.         break;
  4548.       case K_Right:
  4549.       case K_ERight:
  4550.       case K_Down:
  4551.       case K_EDown:    
  4552.       case K_Control_N:
  4553.       case K_Control_F:
  4554.         if (no < help_text_count - 1)
  4555.           if (pane_pos < toplines - 2)
  4556.             pane_pos++;
  4557.           else
  4558.             help_origin++;
  4559.         break;
  4560.       case K_Home:
  4561.       case K_EHome:
  4562.         pane_pos = help_origin = 0;
  4563.         break;
  4564.       case K_End:
  4565.       case K_EEnd:
  4566.         if (help_text_count > toplines - 1)
  4567.         { help_origin = help_text_count - toplines;
  4568.           pane_pos = toplines - 2;
  4569.         }
  4570.         else
  4571.         { help_origin = 0;
  4572.           pane_pos = help_text_count ? help_text_count - 1 : 0;
  4573.         }
  4574.         break;
  4575.       case K_PageDown:
  4576.       case K_EPageDown:
  4577.       case K_Control_V:
  4578.         if (help_origin + toplines <= help_text_count)
  4579.         { help_origin += toplines;
  4580.           if (help_origin + pane_pos >= help_text_count)
  4581.           pane_pos = help_text_count - 1 - help_origin;
  4582.         }
  4583.         break;
  4584.       case K_PageUp:
  4585.       case K_EPageUp:
  4586.         if (help_origin > toplines - 1)
  4587.           help_origin -= toplines - 1;
  4588.         else
  4589.           help_origin = pane_pos = 0;
  4590.         break;
  4591.       case K_Return:
  4592.       case K_Control_G:
  4593.       case K_Space:
  4594.         help_pane_active = 0;
  4595.         code_pane_active = 1;
  4596.         pane = 0;
  4597.         break;
  4598.     }
  4599.   }
  4600.   redraw (0);
  4601. }
  4602. /* ---------------------------------------------------------------------- */
  4603. static void
  4604. view_regs (void)
  4605. { WIN_TEXT read_text;  
  4606.   char *p;
  4607.   int i;
  4608.  
  4609.   init_text (&read_text, "Address Registers");
  4610.   p = malloc (max_cols + 5);
  4611.   for (i = 0; i < MAX_REGISTERS; i++)
  4612.   { sprintf (p, "Register[%c] == %08lx", i + '0', registers[i]);
  4613.     add_text (&read_text, p);
  4614.   }
  4615.   free (p);
  4616.   text_win (read_text, 40, 20);
  4617.   free_text (&read_text);
  4618. }
  4619. /* ---------------------------------------------------------------------- */
  4620. static void
  4621. resize_screen(void)
  4622. { int key, i;
  4623.  
  4624.   while (1)
  4625.   { redraw(-1);
  4626.     key = getykey();
  4627.     if (key == K_Escape)
  4628.     { key = getykey ();
  4629.       if (key == K_Escape)
  4630.         key = K_Control_G;
  4631.     }
  4632.     switch (key)
  4633.     { case K_Up:
  4634.       case K_EUp:
  4635.       case K_Control_P:
  4636.     if (toplines > 3)
  4637.     { toplines--;
  4638.       bottomlines++;
  4639.     }
  4640.     break;
  4641.       case K_Down:
  4642.       case K_EDown:
  4643.       case K_Control_N:
  4644.     if (toplines < rows - 4)
  4645.     { toplines++;
  4646.       bottomlines--;
  4647.     }
  4648.     break;
  4649.       case K_Left:
  4650.       case K_ELeft:
  4651.       case K_Control_B:
  4652.     switch (pane)
  4653.     { case 1:        /* Top middle   */
  4654.       case 2:        /* Top right    */
  4655.         if ((main_x2 > 3) && (main_x2 - main_x1 > 3))
  4656.           main_x2--;
  4657.         break;
  4658.       case 3:        /* Bottom right */
  4659.       case 4:        /* Bottom left  */
  4660.         if (main_x3 > 11 + 2 * data_dump_size)
  4661.           main_x3--;
  4662.         break;
  4663.       default:       /* Top left     */
  4664.         if (main_x1 > 3)
  4665.           main_x1--;
  4666.         break;
  4667.     }
  4668.     break;
  4669.       case K_Right:
  4670.       case K_ERight:
  4671.       case K_Control_F:
  4672.     switch (pane)
  4673.     { case 1:        /* Top middle   */
  4674.       case 2:        /* Top right    */
  4675.         if (main_x2 < cols - 4)
  4676.           main_x2++;
  4677.         break;
  4678.       case 3:        /* Bottom right */
  4679.       case 4:        /* Bottom left  */
  4680.         if (main_x3 < cols - 4)
  4681.           main_x3++;
  4682.         break;
  4683.       default:       /* Top left     */
  4684.         if ((main_x1 < cols - 4) && (main_x2 - main_x1 > 3))
  4685.           main_x1++;
  4686.         break;
  4687.     }
  4688.     break;
  4689.     }
  4690.     if (key == K_Return)
  4691.       break;
  4692.     if (key == K_Control_G)
  4693.       break;
  4694.   }
  4695.   for (i = 0; i < PANECOUNT; i++)
  4696.     switch(i)
  4697.     { case 3:        /* Bottom panes  */
  4698.       case 4:
  4699.     if (pane_positions[i] > bottomlines - 1)
  4700.       pane_positions[i] = bottomlines - 1;
  4701.     break;
  4702.       default:       /* Top panes     */
  4703.     if (pane_positions[i] > toplines - 1)
  4704.       pane_positions[i] = toplines - 1;
  4705.     break;
  4706.     }
  4707.   switch(pane)
  4708.   { case 3:        /* Bottom panes  */
  4709.     case 4:
  4710.       if (pane_pos > bottomlines - 1)
  4711.     pane_pos = bottomlines - 1;
  4712.       break;
  4713.     default:       /* Top panes     */
  4714.       if (pane_pos > toplines - 1)
  4715.     pane_pos = toplines - 1;
  4716.       break;
  4717.   }
  4718.   redraw(0);
  4719. }
  4720. /* ---------------------------------------------------------------------- */
  4721. static void
  4722. setup_io(void)
  4723. {
  4724.   if (!my_read_string("Redirect IO to device: "))
  4725.   {
  4726.     if (strncmp (read_buffer, "con", 3) == 0)
  4727.       using_com_port_num = 0;
  4728.     if (strncmp (read_buffer, "com_one", 7) == 0)
  4729.       using_com_port_num = 1;
  4730.     if (strncmp (read_buffer, "com_two", 7) == 0)
  4731.       using_com_port_num = 2;
  4732.     if (strncmp (read_buffer, "com_three", 9) == 0)
  4733.       using_com_port_num = 3;
  4734.     if (strncmp (read_buffer, "com_four", 8) == 0)
  4735.       using_com_port_num = 4;
  4736.     if (using_com_port_num)
  4737.     { re_init_io (using_com_port_num, rows, cols); 
  4738.       toplines = (rows / 2) + 4;
  4739.       bottomlines = rows - 3 - toplines;
  4740.       main_x1 = cols - 18;
  4741.       main_x2 = cols - 5;
  4742.       main_x3 = 46;
  4743.     }
  4744.     free (code_pane_pos);
  4745.     free (stack_dump_pos);
  4746.     code_pane_pos = malloc ((rows + 2) * sizeof (word32));
  4747.     stack_dump_pos = malloc ((rows + 2) * sizeof (word32));
  4748.     free (debug_screen_save);
  4749.     free (user_screen_save);
  4750.     debug_screen_save = get_screen ();
  4751.     debug_screen_save[1] = debug_screen_save[2] = 0;
  4752.     user_screen_save = get_screen ();
  4753.     user_screen_save[1] = debug_screen_save[2] = 0;
  4754.   }
  4755.   redraw (0);
  4756. }
  4757. /* ---------------------------------------------------------------------- */
  4758. static void
  4759. setup_screen(void)
  4760. {
  4761.   int new_cols, new_rows;
  4762.  
  4763.   if (!my_read_string("Columns: "))
  4764.     {
  4765.       char *endp;
  4766.  
  4767.       new_cols = strtoul(read_buffer, &endp, 10);
  4768.       if (new_cols == 0)
  4769.     new_cols = cols;
  4770.     }
  4771.   else
  4772.     new_cols = cols;
  4773.  
  4774.   if (new_cols < 20)
  4775.     new_cols = 20;
  4776.   if (new_cols > max_cols)
  4777.     new_cols = max_cols;
  4778.  
  4779.   if (!my_read_string("Rows: "))
  4780.     {
  4781.       char *endp;
  4782.  
  4783.       new_rows = strtoul(read_buffer, &endp, 10);
  4784.       if (new_rows == 0)
  4785.     new_rows = rows;
  4786.     }
  4787.   else
  4788.     new_rows = rows;
  4789.  
  4790.   if (new_rows < 15)
  4791.     new_rows = 15;
  4792.   if (new_rows > max_rows)
  4793.     new_rows = max_rows;  
  4794.   
  4795.   re_init_io (using_com_port_num, new_rows, new_cols);
  4796.  
  4797.   toplines = (rows / 2) + 4;
  4798.   bottomlines = rows - 3 - toplines;
  4799.   main_x1 = cols - 18;
  4800.   main_x2 = cols - 5;
  4801.   main_x3 = 46;
  4802.   if (main_x3 > cols)
  4803.     main_x3 = cols - 10;
  4804.  
  4805.   free (code_pane_pos);
  4806.   free (stack_dump_pos);
  4807.  
  4808.   code_pane_pos = malloc ((rows + 2) * sizeof (word32));
  4809.   stack_dump_pos = malloc ((rows + 2) * sizeof (word32));
  4810.  
  4811.   free (debug_screen_save);
  4812.   debug_screen_save = get_screen ();
  4813.   debug_screen_save[1] = debug_screen_save[2] = 0;  /* Patch cursor pos.  */
  4814.  
  4815.   redraw (0);
  4816. }
  4817. /* ---------------------------------------------------------------------- */
  4818. static void
  4819. make_pane_name (void)
  4820. { switch (pane)
  4821.   { case CODE_PANE_NUM:
  4822.       sprintf (active_pane_name, "Code Pane");
  4823.       break;
  4824.     case NPX_PANE_NUM:
  4825.       sprintf (active_pane_name, "NPX Pane");
  4826.       break;
  4827.     case STACK_PANE_NUM:
  4828.       sprintf (active_pane_name, "Stack Pane");
  4829.       break;
  4830.     case INFO_PANE_NUM:
  4831.       sprintf (active_pane_name, "Info Pane");
  4832.       break;
  4833.     case WHEREIS_PANE_NUM:
  4834.       sprintf (active_pane_name, "WhereIs Pane");
  4835.       break;
  4836.     case MODULE_PANE_NUM:
  4837.       sprintf (active_pane_name, "Module Pane");
  4838.       break;
  4839.     case HELP_PANE_NUM:
  4840.       sprintf (active_pane_name, "Help Pane");
  4841.       break;
  4842.   }
  4843. }
  4844. /* ---------------------------------------------------------------------- */
  4845. static int
  4846. make_pane_from_key (int key)
  4847. { switch (key)
  4848.   { case 'B':
  4849.     case 'b':
  4850.       return (203);
  4851.       break;
  4852.     case 'C':
  4853.     case 'c':
  4854.       return (204);
  4855.       break;        
  4856.     case 'D':
  4857.     case 'd':
  4858.       return (205);
  4859.       break;        
  4860.     case 'F':
  4861.     case 'f':
  4862.       return (206);
  4863.       break;        
  4864.     case 'H':
  4865.     case 'h':
  4866.       return (207);
  4867.       break;        
  4868.     case 'I':
  4869.     case 'i':
  4870.       return (208);
  4871.       break;        
  4872.     case 'M':
  4873.     case 'm':
  4874.       return (209);
  4875.       break;        
  4876.     case 'N':
  4877.     case 'n':
  4878.       return (210);
  4879.       break;        
  4880.     case 'R':
  4881.     case 'r':
  4882.       return (211);
  4883.       break;        
  4884.     case 'S':
  4885.     case 's':
  4886.       return (212);
  4887.       break;        
  4888.     case 'W':
  4889.     case 'w':
  4890.       return (213);
  4891.       break;        
  4892.     default:
  4893.       return (999);
  4894.       break;
  4895.   }    
  4896. }
  4897. /* ---------------------------------------------------------------------- */
  4898. static void
  4899. log_current_pane (void)
  4900. { switch (pane)    /* focused pane */
  4901.   { case 1:        /* Top middle */
  4902.       write_log (main_x1 + 1, 2, main_x2, toplines + 1);
  4903.       break;
  4904.     case 2:        /* Top right */
  4905.       write_log (main_x2 + 1, 2, cols - 1, toplines + 1);
  4906.       break;
  4907.     case 3:        /* Bottom right */
  4908.       write_log (main_x3+1, toplines+2, cols-1, rows-1);
  4909.       break;
  4910.     case 4:        /* Bottom left */
  4911.       write_log (1, toplines + 2, main_x3, rows - 1);
  4912.       break;
  4913.     default:       /* Top Left */
  4914.       write_log (1, 2, main_x1, toplines + 1);
  4915.       break;
  4916.   }
  4917. }
  4918. /* ---------------------------------------------------------------------- */
  4919. static void
  4920. current_pane_taller (void)
  4921. { switch (pane)
  4922.   { case 3:  /* Breakpoint */
  4923.     case 4:  /* Data       */   
  4924.       if (toplines > 3)
  4925.       { toplines--;
  4926.         bottomlines++;
  4927.       }
  4928.       break;
  4929.     default:
  4930.       if (bottomlines > 1)
  4931.       { toplines++;
  4932.         bottomlines--;
  4933.       }
  4934.       break;
  4935.   }    
  4936.   redraw (0);
  4937. }
  4938. /* ---------------------------------------------------------------------- */
  4939. static void
  4940. current_pane_wider (void)
  4941. { switch (pane)
  4942.   { case 1:  /* Register   */          
  4943.       if (main_x1 > 3)
  4944.         main_x1--;
  4945.       break;
  4946.     case 2:  /* Flag       */ 
  4947.       break;                             /* No need to enlarge flag pane */
  4948.     case 3:  /* Breakpoint */ 
  4949.       if (main_x3 > 11 + 2 * data_dump_size)
  4950.         main_x3--;   
  4951.       break;
  4952.     case 4:  /* Data       */ 
  4953.       if (main_x3 < cols - 4)
  4954.         main_x3++;
  4955.       break;
  4956.     default: /* TopLeftPane*/ 
  4957.       if ((main_x1 < cols - 4) && (main_x2 - main_x1 > 3))
  4958.         main_x1++;
  4959.       break; 
  4960.   } 
  4961.   redraw (0);
  4962. }
  4963. /* ---------------------------------------------------------------------- */
  4964. static char *
  4965. addr_to_str (char *output, word32 addr)
  4966. { char *name;
  4967.   int32 delta;
  4968.   
  4969.   name = syms_val2name (addr, &delta);
  4970.   if (name[0] != '0')
  4971.     if (delta)
  4972.       sprintf (output, "%s+%#lx", name, delta);
  4973.     else
  4974.       sprintf (output, "%s", name);
  4975.   else
  4976.     sprintf(output,"0x%08lx",addr);
  4977.   return (output);
  4978. }
  4979. /* ---------------------------------------------------------------------- */
  4980. static void
  4981. breakpoint_to_str (char *str, int class, int type, word32 addr,
  4982.                    int length, int count, char *cond)
  4983. { char temp[200];
  4984.  
  4985.   sprintf (str, "-class %s -type %s -at %s -length %d ",
  4986.            class == 0 ? "normal" : class == 1 ? "count_down" : "conditional",
  4987.            type == 0 ? "code" : type == 1 ? "data_write" : "data_read",
  4988.            addr_to_str (temp, addr),
  4989.            length
  4990.           );
  4991.   if (class == 1)
  4992.     sprintf (str + strlen (str), "-count %d", count);
  4993.   if (class == 2)
  4994.     sprintf (str + strlen (str), "-condition %s", cond);
  4995.   sprintf (str + strlen (str), "%c\n", 0x0d);
  4996. }
  4997. /* ---------------------------------------------------------------------- */
  4998. static PARSE_DEF bp_def[] = {
  4999.        {"-class"    , STR_TYPE, {0}},
  5000.        {"-type"     , STR_TYPE, {0}},
  5001.        {"-at"       , STR_TYPE, {0}},
  5002.        {"-length"   , INT_TYPE, {0}},
  5003.        {"-count"    , INT_TYPE, {0}},
  5004.        {"-condition", STR_TYPE, {0}},
  5005.        {0           , 0       , {0}}
  5006. };
  5007. /* ---------------------------------------------------------------------- */
  5008. static int
  5009. str_to_breakpoint (char *str, int *class, int *type, word32 *addr,
  5010.                    int *length, int *count, char *cond)
  5011. { int ok;
  5012.   char s_class[64], s_type[64], s_addr[128];
  5013.  
  5014.   s_class[0] = 0; bp_def[0].val.s_val = s_class;
  5015.   s_type[0]  = 0; bp_def[1].val.s_val = s_type;
  5016.   s_addr[0]  = 0; bp_def[2].val.s_val = s_addr;
  5017.   *length    = 4; bp_def[3].val.i_val = length;
  5018.   *count     = 0; bp_def[4].val.i_val = count;
  5019.   cond[0]    = 0; bp_def[5].val.s_val = cond;
  5020.   
  5021.   parse_string (bp_def, str);
  5022.   if (stricmp (s_class, "count_down") == 0)
  5023.     *class = 1;
  5024.   else if (stricmp (s_class, "conditional") == 0)
  5025.     *class = 2;
  5026.   else
  5027.     *class = 0;
  5028.   if (stricmp (s_type, "data_write") == 0)
  5029.     *type = 1;
  5030.   else if (stricmp (s_type, "data_read") == 0)
  5031.     *type = 3;
  5032.   else
  5033.     *type = 0;
  5034.   *addr = parse_expression (4, s_addr, &ok);
  5035.   if (ok != ParseError_ok)
  5036.     ok = 0;
  5037.   else
  5038.     ok = 1;
  5039.   if (*class == 2 && cond[0] == 0)
  5040.     ok = 0;
  5041.   return (ok);
  5042. }
  5043. /* ---------------------------------------------------------------------- */
  5044. static PARSE_DEF reg_def[] = {
  5045.        {"-number"   , STR_TYPE, {0}},
  5046.        {"-value"    , STR_TYPE, {0}},
  5047.        {0           , 0       , {0}}
  5048. };
  5049. /* ---------------------------------------------------------------------- */
  5050. static int
  5051. str_to_reg (char *str, char *index, word32 *addr)
  5052. { int ok;
  5053.   char s_index[32], s_addr[128];
  5054.   
  5055.   s_index[0] = 0; reg_def[0].val.s_val = s_index;
  5056.   s_addr[0]  = 0; reg_def[1].val.s_val = s_addr;
  5057.   
  5058.   parse_string (reg_def, str);
  5059.   if (s_index[0])
  5060.     *index = *s_index - '0';
  5061.   else
  5062.     return (0);
  5063.   *addr = parse_expression (4, s_addr, &ok);
  5064.   if (ok != ParseError_ok)
  5065.     return (0);
  5066.   return (1);
  5067. }
  5068. /* ---------------------------------------------------------------------- */
  5069. static PARSE_DEF pa_def[] = {
  5070.        {"-start"   , STR_TYPE, {0}},
  5071.        {"-stop"    , STR_TYPE, {0}},
  5072.        {0          , 0       , {0}}
  5073. };
  5074. /* ---------------------------------------------------------------------- */
  5075. static int
  5076. str_to_pa (char *str, word32 *addr1, word32 *addr2)
  5077. { int ok;
  5078.   char s_start[128], s_stop[128];
  5079.   
  5080.   s_start[0] = 0; pa_def[0].val.s_val = s_start;
  5081.   s_stop[0]  = 0; pa_def[1].val.s_val = s_stop;
  5082.   
  5083.   parse_string (pa_def, str);
  5084.   *addr1 = parse_expression (4, s_start, &ok);
  5085.   if (ok != ParseError_ok)
  5086.     return (0);
  5087.   *addr2 = parse_expression (4, s_stop, &ok);
  5088.   if (ok != ParseError_ok)
  5089.     return (0);
  5090.   return (1);
  5091. }
  5092. /* ---------------------------------------------------------------------- */
  5093. static PARSE_DEF pane_def[] = {
  5094.        {"-top_lines"    , INT_TYPE, {0}},
  5095.        {"-top_left_cols", INT_TYPE, {0}},
  5096.        {"-top_mid_cols" , INT_TYPE, {0}},
  5097.        {"-bot_left_cols", INT_TYPE, {0}},
  5098.        {0               , 0       , {0}}
  5099. };
  5100. /* ---------------------------------------------------------------------- */
  5101. static int
  5102. str_to_pane (char *str, int *tl, int *x1, int *x2, int *x3)
  5103. { pane_def[0].val.i_val = tl;
  5104.   pane_def[1].val.i_val = x1;
  5105.   pane_def[2].val.i_val = x2;
  5106.   pane_def[3].val.i_val = x3;
  5107.  
  5108.   parse_string (pane_def, str);
  5109.   return (1);
  5110. }
  5111. /* ---------------------------------------------------------------------- */
  5112. static int
  5113. save_context (int save_bp, int save_reg, int save_pa, int save_pane, 
  5114.               char *filename)
  5115. { FILE *f;
  5116.   int i;
  5117.   char temp[200];
  5118.  
  5119.   f = fopen (filename, "wb");
  5120.   if (!f)
  5121.     return (0);
  5122.   if (save_bp)
  5123.   { fputs ("##\015\n", f);
  5124.     fputs ("# Breakpoint information\015\n", f);
  5125.     fputs ("##\015\n", f);
  5126.     fputs (" \015\n", f);
  5127.     for (i = 0; i < breakpoint_count; i++)
  5128.     { sprintf (read_buffer, "bre ");
  5129.       breakpoint_to_str (read_buffer + strlen (read_buffer),
  5130.                          breakpoint_table[i].sub_type,
  5131.                          breakpoint_table[i].type,
  5132.                          breakpoint_table[i].addr,
  5133.                          breakpoint_table[i].length,
  5134.                          breakpoint_table[i].count,
  5135.                          breakpoint_table[i].condition
  5136.                         );
  5137.       fputs (read_buffer, f);
  5138.     }
  5139.     fputs (" \015\n", f);
  5140.   }
  5141.   if (save_reg)
  5142.   { fputs ("##\015\n", f);
  5143.     fputs ("# Debugger registers\015\n", f);
  5144.     fputs ("##\015\n", f);
  5145.     fputs (" \015\n", f);
  5146.     for (i = 0; i < MAX_REGISTERS; i++)
  5147.       if (registers[i])
  5148.       { sprintf (read_buffer, "reg -number %c -value %s\015\n",
  5149.                  i + '0',
  5150.                  addr_to_str (temp, registers[i])
  5151.                 );
  5152.         fputs (read_buffer, f);
  5153.       }
  5154.     fputs (" \015\n", f);
  5155.   }
  5156.   if (save_pa)
  5157.   { fputs ("##\015\n", f);
  5158.     fputs ("# Performance Analyzer\015\n", f);
  5159.     fputs ("##\015\n", f);
  5160.     fputs (" \015\n", f);
  5161.     sprintf (read_buffer, "pa -start %s ",
  5162.              addr_to_str (temp, evaluation_data[0].start_addr)
  5163.             );
  5164.     sprintf (read_buffer + strlen (read_buffer), "-stop %s\015\n",
  5165.              addr_to_str (temp, evaluation_data[EVAL_SEGMENTS - 1].stop_addr)
  5166.             );
  5167.     fputs (read_buffer, f);
  5168.     fputs (" \015\n", f);
  5169.   }
  5170.   if (save_pane)
  5171.   { fputs ("##\015\n", f);
  5172.     fputs ("# Pane information\015\n", f);
  5173.     fputs ("##\015\n", f);
  5174.     fputs (" \015\n", f);
  5175.     sprintf (read_buffer,
  5176.              "pane -top_lines %d -top_left_cols %d -top_mid_cols %d -bot_left_cols %d\015\n",
  5177.              toplines, main_x1 - 1, main_x2 - main_x1 - 1, main_x3 - 1
  5178.             );
  5179.     fputs (read_buffer, f);
  5180.     fputs (" \015\n", f);
  5181.   }
  5182.   fclose (f);
  5183.   return (1);
  5184. }
  5185. /* ---------------------------------------------------------------------- */
  5186. static int
  5187. load_context (int load_bp, int load_reg, int load_pa, int load_pane, 
  5188.               char *filename, int startup_load)
  5189. { FILE *f;                                                               
  5190.   int err, temp;
  5191.   char command[64];
  5192.  
  5193.   if (startup_load)
  5194.   { f = fopen (startup_file, "rb");
  5195.     if (!f)
  5196.       return (0);
  5197.   } else
  5198.   { f = fopen (filename, "rb");
  5199.     if (!f)
  5200.     { message (CL_Error, "Error reading from file %s", filename);
  5201.       return (0);
  5202.     }
  5203.   }
  5204.   err = load_bp +
  5205.         ((load_reg & 1) << 1) +
  5206.         ((load_pa & 1) << 2) +
  5207.         ((load_pane & 1) << 3);
  5208.   while (fgets (read_buffer, 1024, f))
  5209.   { read_buffer[strlen (read_buffer) - 1] = 0;
  5210.     if (sscanf (read_buffer, "%s%n", command, &temp) >= 1)
  5211.     { if (stricmp (command, "bre") == 0)
  5212.       { if (load_bp)
  5213.         { int class, type, length, count;
  5214.           word32 addr;
  5215.           char cond[200];
  5216.  
  5217.           count = 0;
  5218.           cond[0] = 0;
  5219.           str_to_breakpoint (read_buffer + temp,
  5220.                              &class, &type, &addr, &length, &count, cond);
  5221.           temp = set_breakpoint (type, length, addr);
  5222.           breakpoint_table[temp].sub_type = class;
  5223.           breakpoint_table[temp].count = count;
  5224.           strcpy (breakpoint_table[temp].condition, cond);
  5225.         }
  5226.         err &= ~1;
  5227.       } else if (stricmp (command, "reg") == 0)
  5228.       { if (load_reg)
  5229.     { char index;
  5230.       word32 addr;
  5231.  
  5232.       if (str_to_reg ((char *)(read_buffer + temp), &index, &addr))
  5233.       { registers[(int)index] = addr;
  5234.             err &= ~2;
  5235.           }
  5236.         }
  5237.       } else if (stricmp (command, "pa") == 0)
  5238.       { if (load_pa)
  5239.         { word32 addr1, addr2;
  5240.  
  5241.       if (str_to_pa ((char *)(read_buffer + temp), &addr1, &addr2))
  5242.       { init_eval_data (addr1, addr2);
  5243.         err &= ~4;
  5244.       }
  5245.     }
  5246.       } else if (stricmp (command, "pane") == 0)
  5247.       { if (load_pane)
  5248.     { int tl = 0, x1 = 0, x2 = 0, x3 = 0;
  5249.  
  5250.       if (str_to_pane ((char *)(read_buffer + temp), &tl, &x1, &x2, &x3))
  5251.       { if (tl < rows - 5 && tl > 3)
  5252.         { toplines = tl;
  5253.           bottomlines = rows - 4 - toplines;
  5254.         }
  5255.         if (x1 > 1 && x1 < cols - 5)
  5256.         { main_x1 = x1 + 1;
  5257.           if (main_x2 - main_x1 < 2)
  5258.         main_x2 = main_x1 + 2;
  5259.         }
  5260.         if (x2 > 0 && main_x1 + x2 < cols - 2)
  5261.           main_x2 = main_x1 + x2 + 1;
  5262.         if (x3 > 11 + 2 * data_dump_size && main_x3 < cols - 5)
  5263.           main_x3 = x3 + 1;
  5264.         err &= ~8;
  5265.       }
  5266.     }
  5267.       }
  5268.     }
  5269.   }
  5270.   fclose (f);
  5271.   if (startup_load)
  5272.     return (1);
  5273.   redraw (0);
  5274.   if (err)
  5275.     message (CL_Error, "File has no %s%s%s%s information",
  5276.          err & 1 ? "breakpoints" : "",
  5277.              err & 2 ? (err & 1 ? ", registers" : "registers") : "",
  5278.              err & 4 ? (err & 3 ? ", P.A. data" : "P.A. data") : "",
  5279.              err & 8 ? (err & 7 ? ", pane layouts" : "pane layouts") : "");
  5280.   else
  5281.     message (CL_Info, "Requested context has been successfully loaded.");
  5282.   return (1);
  5283. }
  5284. /* ---------------------------------------------------------------------- */
  5285. static void
  5286. in_ck (char *output, char *input, word32 addr)
  5287. { sprintf (output, "%s", *(int *)addr ? "[X]" : "[ ]");
  5288. }
  5289. /* ---------------------------------------------------------------------- */
  5290. static int
  5291. ed_ck (char *text, word32 addr, int x, int y, int len, int *key)
  5292. { if (*key == K_Return || *key == K_Space)/* Only these keys are accepted */
  5293.   { if (*(int *)addr)
  5294.       *(int *)addr = 0;
  5295.     else
  5296.       *(int *)addr = 1;
  5297.   }
  5298.   *key = 0;
  5299.   return 1;
  5300. }          
  5301. /* ---------------------------------------------------------------------- */
  5302. static void
  5303. save_load_context (void)
  5304. { int ret = 7;
  5305.   static int save_bp = 1, save_reg = 0, save_pa = 0, save_pane = 0;
  5306.   static char ct_filename[81];
  5307.   static DIALOG_ITEM dialog_data[] = {
  5308.     {"Breakpoints          :", 0 , 03, 1, format_asis, eval_word, in_ck    , ed_ck },
  5309.     {"Registers            :", 0 , 03, 1, format_asis, eval_word, in_ck    , ed_ck },
  5310.     {"Performance Analizer :", 0 , 03, 1, format_asis, eval_word, in_ck    , ed_ck },
  5311.     {"Pane positions       :", 0 , 03, 1, format_asis, eval_word, in_ck    , ed_ck },
  5312.     {"Filename             :", 0 , 80, 1, format_asis, eval_asis, init_asis, editor},
  5313.     {0                       , 0 , 00 ,0, 0          , 0        , 0        , 0     }
  5314.   };
  5315.   static BUTTON_ITEM button_data[] = {
  5316.     {"  Save  ", 0, action_done},
  5317.     {"  Load  ", 0, action_done},
  5318.     {" Cancel ", 0, action_done},
  5319.     {0         , 0, 0          }
  5320.   };
  5321.  
  5322.   dialog_data[0].return_addr = (word32)&save_bp;
  5323.   dialog_data[1].return_addr = (word32)&save_reg;
  5324.   dialog_data[2].return_addr = (word32)&save_pa;
  5325.   dialog_data[3].return_addr = (word32)&save_pane;
  5326.   dialog_data[4].return_addr = (word32)&ct_filename;
  5327.   dialog ("Debugger Context", dialog_data, button_data, &ret);
  5328.   switch (ret)
  5329.   { case 1:
  5330.       if (ct_filename[0])
  5331.         if (save_context (save_bp, save_reg, save_pa, save_pane, ct_filename))
  5332.            message (CL_Info, "Requested context has been successfully saved.");
  5333.         else
  5334.            message (CL_Error, "Error writing to file %s", ct_filename);
  5335.       break;
  5336.     case 2:
  5337.       if (ct_filename[0])
  5338.         load_context (save_bp, save_reg, save_pa, save_pane, ct_filename, 0);
  5339.       break;
  5340.     default:
  5341.       redraw (0);
  5342.   }
  5343. }
  5344. /* ---------------------------------------------------------------------- */
  5345. void
  5346. debugger (void)
  5347. {
  5348.   int oldpane, lastpane, bar_select, pop_select, command;
  5349.   static void (*keyhandlers[PANECOUNT])(int) =
  5350.     {
  5351.       &code_pane_command,          /*  0 */
  5352.       ®ister_pane_command,      /*  1 */
  5353.       &flag_pane_command,          /*  2 */
  5354.       &breakpoint_pane_command,    /*  3 */
  5355.       &data_pane_command,          /*  4 */
  5356.       &npx_pane_command,           /*  5 */
  5357.       &stack_pane_command,         /*  6 */
  5358.       &info_pane_command,          /*  7 */
  5359.       &whereis_pane_command,       /*  8 */
  5360.       &module_pane_command,        /*  9 */
  5361.       &help_pane_command           /* 10 */
  5362.     };
  5363.  
  5364.   main_entry = syms_name2val ("_main");
  5365.   first_step = !undefined_symbol;
  5366.   initialize ();
  5367.   if (startup_file[0] != 0)
  5368.     if (load_context (1, 1, 1, 1, startup_file, 1))
  5369.       message (CL_Info, "Succesfully loaded start-up file %s.", startup_file);
  5370.   can_longjmp = 1;
  5371.   setjmp (debugger_jmpbuf);
  5372.   lastpane = oldpane = -1;                           
  5373.   show_menu_bar (Main_Menu);
  5374.   Main_Menu[0].type = 1;
  5375.  
  5376.   while (1)
  5377.     {
  5378.       int key;
  5379.  
  5380.       if (pane < 1 || pane > 4)
  5381.     pane = code_pane_active ? 0
  5382.       : (npx_pane_active ? 5
  5383.          : (stack_pane_active ? 6
  5384.         : (info_pane_active ? 7
  5385.            : (whereis_pane_active ? 8
  5386.               : (module_pane_active ? 9
  5387.              : (help_pane_active ? 10
  5388.                 : (abort (), -1)))))));
  5389.       if (pane == oldpane)
  5390.     pane_positions[pane] = pane_pos;
  5391.       else
  5392.     {
  5393.       pane_pos = pane_positions[pane];
  5394.           lastpane = oldpane;
  5395.       oldpane = pane;
  5396.           make_pane_name ();
  5397.       redraw (0);
  5398.           if (whereis_pane_active && !whereis_sym_count)
  5399.              init_whereis_sym ();
  5400.     } 
  5401.       escaped   = 0; 
  5402.       control_c = 0;
  5403.       control_x = 0;
  5404.       switch (key = getykey ()) 
  5405.       { case K_Escape:
  5406.           escaped = 1;
  5407.           key = getykey ();
  5408.           break;
  5409.         case K_Control_C:
  5410.           control_c = 1;
  5411.           key = getykey ();
  5412.           break;
  5413.         case K_Control_X:
  5414.           control_x = 1;
  5415.           key = getykey ();
  5416.           break;
  5417.       }                  
  5418.       command = 0; 
  5419.       if (escaped)
  5420.         switch (key)
  5421.     { case K_Escape:                  /* Esc-Esc           */           
  5422.             pop_select = 0;
  5423.             if (!running_xsupport)
  5424.             { menu (Main_Menu, &bar_select, &pop_select);
  5425.               command = bar_select * 100 + pop_select;  
  5426.             } else
  5427.             { command = 999;
  5428.               if (extern_data_support (data_dump_origin + 
  5429.                    pane_positions[DATA_PANE_NUM]))
  5430.               { running_xsupport = 0;
  5431.                 redraw (0);
  5432.               }
  5433.             }
  5434.             break;
  5435.           case K_Control_P:               /* Esc-^P            */
  5436.             key = getykey ();
  5437.             command = make_pane_from_key (key);
  5438.             break;     
  5439.           default:
  5440.             command = 0;
  5441.             break;
  5442.         }                                                        
  5443.       if (control_x)
  5444.       { command = 999;
  5445.         switch (key)
  5446.     { case K_Control_C:               /* <=> F-Exit        */
  5447.             if (confirm ("Are you sure (y/n)? "))
  5448.               command = 108;
  5449.             break;
  5450.       case K_Control_V:               /* <=> F-Context     */
  5451.             command = 107;
  5452.             break;
  5453.       case K_Control_W:               /* Write Log         */
  5454.             log_current_pane ();
  5455.             break;
  5456.       case K_Control_F:               /* Read Log          */
  5457.             read_log ();
  5458.             break;
  5459.       case K_Control_E:               /* <=> M-Evaluate    */
  5460.             command = 402;
  5461.             break;                                       
  5462.           case K_Control_X:               /* Prev. Reflexive   */
  5463.             if ((lastpane >= 0) && (lastpane < PANECOUNT))
  5464.             { command = pane;
  5465.               pane = lastpane;
  5466.               lastpane = command;
  5467.               command = 999;
  5468.             } 
  5469.             break;
  5470.           case '^':                       /* Taller            */
  5471.             current_pane_taller ();
  5472.             break;
  5473.           case '}':                       /* Wider             */
  5474.             current_pane_wider ();
  5475.             break;
  5476.       case '<':                       /* Scroll left       */
  5477.             pane_offset[pane] += SCROLL_COUNT; 
  5478.             redraw (0);
  5479.             break;       
  5480.       case '>':                       /* Scroll right      */
  5481.             if (pane_offset[pane] > 0)
  5482.               pane_offset[pane] -= SCROLL_COUNT; 
  5483.             redraw (0);
  5484.             break;        
  5485.           case 'm':                       /* Color / Mono      */
  5486.           case 'M':
  5487.             if (screen_attr_normal == screen_attr_asm)
  5488.               command = 105;
  5489.             else
  5490.               command = 104;
  5491.             break;
  5492.           case 'o':
  5493.           case 'O':                       /* Next pane == Tab  */
  5494.             control_x = 0;
  5495.             key = K_Tab;
  5496.             break;
  5497.           default:
  5498.             command = 0;
  5499.             break;
  5500.         }             
  5501.       }
  5502.       if (control_c)
  5503.       { command = 0;                      /* No command defined*/
  5504.       }
  5505.       if (!(escaped || control_x || control_c))
  5506.       { command = 999;
  5507.         switch (key)
  5508.     { case K_Tab:                                            
  5509.             if (pane < 1 || pane > 4)
  5510.           pane = 1;
  5511.             else
  5512.           pane++;
  5513.         break;
  5514.           case K_BackTab:  
  5515.             if (pane < 1 || pane > 4)
  5516.               pane = 4;
  5517.             else
  5518.               pane--;
  5519.             break;
  5520.           case K_Control_H:            /* Global - Help    */
  5521.             command = 207;
  5522.             break;         
  5523.           case K_Control_R:            /* Global - Run     */
  5524.             step (2);                                          
  5525.             break;         
  5526.           case K_Control_L:            /* Global - Refresh */
  5527.             command = 403;
  5528.             break;
  5529.           case K_Control_Z:            /* Global - User Scr*/
  5530.             command = 401;
  5531.             break;
  5532.           default:    
  5533.             command = 0;
  5534.             break;
  5535.         }               
  5536.       }
  5537.       switch (command)
  5538.       {  case 101:                     /* File - Log       */
  5539.         switch (pane)    /* focused pane */
  5540.         { case 1:        /* Top middle */
  5541.            read_write_log (main_x1 + 1, 2, main_x2, toplines + 1);
  5542.            break;
  5543.          case 2:        /* Top right */
  5544.            read_write_log (main_x2 + 1, 2, cols - 1, toplines + 1);
  5545.            break;
  5546.          case 3:        /* Bottom right */
  5547.            read_write_log (main_x3+1, toplines+2, cols-1, rows-1);
  5548.            break;
  5549.          case 4:        /* Bottom left */
  5550.            read_write_log (1, toplines + 2, main_x3, rows - 1);
  5551.            break;
  5552.          default:       /* Top Left */
  5553.            read_write_log (1, 2, main_x1, toplines + 1);
  5554.            break;
  5555.        }
  5556.        break;
  5557.          case 102:                    /* File - Registers */
  5558.            view_regs ();
  5559.            break;
  5560.          case 103:                    /* File - Resize    */
  5561.            setup_screen ();
  5562.            break;
  5563.          case 104:                    /* File - Mono mode */
  5564.            init_color (0);
  5565.            oldpane = -1;
  5566.            break;
  5567.          case 105:                    /* File - Color    */
  5568.            init_color (1);
  5569.            oldpane = -1;
  5570.            break;
  5571.          case 106:                    /* File - Redirect */
  5572.            setup_io();
  5573.            break; 
  5574.          case 107:                    /* File - Context  */
  5575.            save_load_context ();
  5576.            break;
  5577.          case 108:                    /* File - Exit     */
  5578.            user_screen ();
  5579.            can_longjmp = 0;
  5580.            if (using_com_port_num)
  5581.              com_done();
  5582.            if (timer_is_set)
  5583.              reset_timer ();
  5584.            return;
  5585.          case 201:                    /* Pane - Previous */
  5586.            if (pane < 1 || pane > 4)
  5587.              pane = 4;
  5588.            else
  5589.              pane--;
  5590.            break;
  5591.          case 202:                    /* Pane - Next     */
  5592.            if (pane < 1 || pane > 4)
  5593.              pane = 1;
  5594.            else
  5595.              pane++;
  5596.            break;
  5597.          case 203:                    /* Pane - Data     */
  5598.            pane = 3;
  5599.            break;
  5600.          case 205:                    /* Pane - Breakpoin*/
  5601.            pane = 4;
  5602.            break;
  5603.          case 206:                    /* Pane - Flags    */
  5604.            pane = 2;
  5605.            break;
  5606.          case 211:                    /* Pane - Registers*/
  5607.            pane = 1;
  5608.            break;
  5609.          case 204:                    /* Pane - Code     */
  5610.          case 207:                    /* Pane - Help     */
  5611.          case 208:                    /* Pane - Info     */
  5612.          case 209:                    /* Pane - Module   */
  5613.          case 210:                    /* Pane - Npx      */
  5614.          case 212:                    /* Pane - Stack    */
  5615.          case 213:                    /* Pane - Where-is */
  5616.            code_pane_active    = (command == 204);
  5617.            help_pane_active    = (command == 207);
  5618.            info_pane_active    = (command == 208);
  5619.            module_pane_active  = (command == 209);
  5620.            npx_pane_active     = (command == 210);
  5621.            stack_pane_active   = (command == 212);
  5622.               whereis_pane_active = (command == 213);
  5623.            pane = 0;                                                     
  5624.            if (npx_pane_active && !has_npx)
  5625.            { message (CL_Error, "NPX not present");
  5626.              npx_pane_active = 0;
  5627.              code_pane_active = 1;
  5628.            }
  5629.            break;
  5630.          case 214:                    /* Pane - Resize   */
  5631.            resize_screen();
  5632.            show_menu_bar (Main_Menu);
  5633.            oldpane = -1; /* Force redraw.  */
  5634.            break;
  5635.          case 300:                    /* Local */
  5636.            keyhandlers[pane] (0);
  5637.            break;
  5638.          case 401:                    /* Misc - User Scre*/
  5639.            user_screen ();
  5640.            (void) getykey ();
  5641.            debug_screen ();
  5642.            break;
  5643.          case 402:                    /* Misc - Evaluate */
  5644.          { int res, ok;
  5645.            res = read_eval (&ok, "");
  5646.            if (ok)
  5647.              message (CL_Msg, "\"%s\" -> %d (0x%08lx)",
  5648.                   read_buffer, res, (word32) res);
  5649.            break;
  5650.          }
  5651.          case 403:                    /* Misc - Refresh  */
  5652.            re_start_transfer ();
  5653.            redraw (0);
  5654.            break;
  5655.          case 501:                    /* Help - About    */
  5656.            message (CL_Info, 
  5657.                     "Ladybug version %d.%02d", MAJOR_VER, MINOR_VER);
  5658.            break;
  5659.          case 502:                    /* Help - Help     */
  5660.            code_pane_active    = 0;
  5661.            info_pane_active    = 0;
  5662.            module_pane_active  = 0;
  5663.            npx_pane_active     = 0;
  5664.            stack_pane_active   = 0;
  5665.               whereis_pane_active = 0;
  5666.            help_pane_active    = 1;
  5667.            oldpane = -1; /* Force redraw.  */
  5668.            break;
  5669.          case 999:                    /* Executed command*/
  5670.            break;
  5671.          default:                     /* Not global keys */
  5672.            keyhandlers[pane] (key);
  5673.            break;
  5674.       }          
  5675.     }
  5676. }
  5677. /* ----------------------------------------------------------------------
  5678.    It's a mystery to me --- the game commences
  5679.    for the usual fee --- plus expenses
  5680.    confidential information --- it's in a diary
  5681.    this is my investigation --- it's not a public inquiry
  5682.  
  5683.    -- Mark Knopfler, "Private Investigations"
  5684. ---------------------------------------------------------------------- */
  5685.